From: Rob Richards Date: Thu, 5 Jun 2003 17:10:13 +0000 (+0000) Subject: Inital cut of new xsl extension X-Git-Tag: RELEASE_1_0_2~414 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=848795e3f91dbf5b43f9ca3e8f86ce5c4f489000;p=php Inital cut of new xsl extension interoperates with new dom extension PHP5 only --- diff --git a/ext/xsl/config.m4 b/ext/xsl/config.m4 new file mode 100644 index 0000000000..2b5e0ebacd --- /dev/null +++ b/ext/xsl/config.m4 @@ -0,0 +1,67 @@ +dnl +dnl $Id$ +dnl +AC_DEFUN(PHP_XSL_CHECK_VERSION,[ + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=-I$XSL_DIR/include + AC_MSG_CHECKING(for libxslt version) + AC_EGREP_CPP(yes,[ +#include +#if LIBXSLT_VERSION >= 10018 + yes +#endif + ],[ + AC_MSG_RESULT(>= 1.0.18) + ],[ + AC_MSG_ERROR(libxslt version 1.0.18 or greater required.) + ]) + CPPFLAGS=$old_CPPFLAGS +]) + +PHP_ARG_WITH(xsl, for XSL support, +[ --with-xsl[=DIR] Include new DOM support (requires libxml >= 2.4.14). + DIR is the libxml install directory.]) + + + +if test "$PHP_XSL" != "no"; then + + if test -r $PHP_XSL/include/libxslt/transform.h; then + XSL_DIR=$PHP_XSL + else + for i in /usr/local /usr; do + test -r $i/include/libxslt/transform.h && XSL_DIR=$i + done + fi + + if test -z "$XSL_DIR"; then + AC_MSG_RESULT(not found) + AC_MSG_ERROR(Please reinstall the libxslt >= 1.0.3 distribution) + fi + + PHP_XSL_CHECK_VERSION + + XSLT_CONFIG=$XSL_DIR/bin/xslt-config + + if test -x $XSLT_CONFIG; then + DOM_LIBS=`$XSLT_CONFIG --libs` + DOM_INCLUDES=`$XSLT_CONFIG --cflags` + AC_MSG_RESULT(found xslt-config in $XSLT_CONFIG) + PHP_EVAL_LIBLINE($DOM_LIBS, XSL_SHARED_LIBADD) + CFLAGS="$CFLAGS $DOM_INCLUDES" + else + PHP_ADD_LIBRARY_WITH_PATH($DOM_LIBNAME, $XSL_DIR/lib, XSL_SHARED_LIBADD) + PHP_ADD_INCLUDE($XSL_DIR/include) + fi + + + AC_DEFINE(HAVE_XSL,1,[ ]) + PHP_NEW_EXTENSION(xsl, php_xsl.c xsltprocessor.c, $ext_shared) + PHP_SUBST(XSL_SHARED_LIBADD) +fi + + + + + + diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c new file mode 100644 index 0000000000..9b9562b9b2 --- /dev/null +++ b/ext/xsl/php_xsl.c @@ -0,0 +1,309 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Christian Stocker | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_ini.h" +#include "zend_execute_locks.h" +#include "ext/standard/info.h" +#include "php_xsl.h" + +/* If you declare any globals in php_xsl.h uncomment this: +ZEND_DECLARE_MODULE_GLOBALS(xsl) +*/ + +/* True global resources - no need for thread safety here */ + +static HashTable classes; +/* not used right now +static zend_object_handlers xsl_object_handlers; +static HashTable xsl_xsltprocessor_prop_handlers; +*/ + +/* {{{ xsl_functions[] + * + * Every user visible function must have an entry in xsl_functions[]. + */ +function_entry xsl_functions[] = { + {NULL, NULL, NULL} /* Must be the last line in xsl_functions[] */ +}; +/* }}} */ + +/* {{{ xsl_module_entry + */ +zend_module_entry xsl_module_entry = { +#if ZEND_MODULE_API_NO >= 20010901 + STANDARD_MODULE_HEADER, +#endif + "xsl", + xsl_functions, + PHP_MINIT(xsl), + PHP_MSHUTDOWN(xsl), + PHP_RINIT(xsl), /* Replace with NULL if there's nothing to do at request start */ + PHP_RSHUTDOWN(xsl), /* Replace with NULL if there's nothing to do at request end */ + PHP_MINFO(xsl), +#if ZEND_MODULE_API_NO >= 20010901 + "0.1", /* Replace with version number for your extension */ +#endif + STANDARD_MODULE_PROPERTIES +}; +/* }}} */ + +#ifdef COMPILE_DL_XSL +ZEND_GET_MODULE(xsl) +#endif + + +/************ +* copied from php_dom .... should be in a common file... +**********/ + + +typedef int (*dom_read_t)(xsl_object *obj, zval **retval TSRMLS_DC); +typedef int (*dom_write_t)(xsl_object *obj, zval *newval TSRMLS_DC); + +typedef struct _dom_prop_handler { + dom_read_t read_func; + dom_write_t write_func; +} dom_prop_handler; + +/* end copied from php_dom.c */ + +/* {{{ xsl_objects_dtor */ +void xsl_objects_dtor(void *object, zend_object_handle handle TSRMLS_DC) +{ + /* TODO */ + xsl_object *intern = (xsl_object *)object; + + zend_hash_destroy(intern->std.properties); + FREE_HASHTABLE(intern->std.properties); + + zend_hash_destroy(intern->parameter); + FREE_HASHTABLE(intern->parameter); + + if (intern->ptr) { + /* free wrapper */ + if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) { + ((xsltStylesheetPtr) intern->ptr)->_private = NULL; + } + /* libxslt uses _private for itself, so turning of the deregistering is maybe a solution + we copied the doc at import, so it shouldn't be possible to be used from php land */ + xsltFreeStylesheet((xsltStylesheetPtr) intern->ptr); + intern->ptr = NULL; + } + efree(object); +} +/* }}} */ +/* {{{ xsl_objects_new */ +zend_object_value xsl_objects_new(zend_class_entry *class_type TSRMLS_DC) +{ + zend_object_value retval; + xsl_object *intern; + zend_class_entry *base_class; + zval *tmp; + + intern = emalloc(sizeof(xsl_object)); + intern->std.ce = class_type; + intern->std.in_get = 0; + intern->std.in_set = 0; + intern->ptr = NULL; + intern->node_list = NULL; + intern->prop_handler = NULL; + intern->parameter = NULL; + + base_class = class_type; + while(base_class->type != ZEND_INTERNAL_CLASS && base_class->parent != NULL) { + base_class = base_class->parent; + } + + zend_hash_find(&classes, base_class->name , base_class->name_length + 1, &intern->prop_handler); + + ALLOC_HASHTABLE(intern->std.properties); + zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); + ALLOC_HASHTABLE(intern->parameter); + zend_hash_init(intern->parameter, 0, NULL, ZVAL_PTR_DTOR, 0); + retval.handle = zend_objects_store_put(intern, xsl_objects_dtor, dom_objects_clone TSRMLS_CC); + retval.handlers = &dom_object_handlers; + return retval; +} +/* }}} */ + +/* {{{ PHP_MINIT_FUNCTION + */ +PHP_MINIT_FUNCTION(xsl) +{ + + zend_class_entry ce; + zend_hash_init(&classes, 0, NULL, NULL, 1); + + memcpy(&dom_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + dom_object_handlers.read_property = dom_read_property; + dom_object_handlers.write_property = dom_write_property; + + REGISTER_XSL_CLASS(ce, "xsltprocessor", NULL, php_xsl_xsltprocessor_class_functions, xsl_xsltprocessor_class_entry); + return SUCCESS; +} +/* }}} */ + +/* {{{ xsl_object_get_data */ +zval *xsl_object_get_data(void *obj) +{ + zval *dom_wrapper; + dom_wrapper = ((xsltStylesheetPtr) obj)->_private; + return dom_wrapper; +} +/* }}} */ + +/* {{{ xsl_object_set_data */ +static void xsl_object_set_data(void *obj, zval *wrapper TSRMLS_DC) +{ + ((xsltStylesheetPtr) obj)->_private = wrapper; +} +/* }}} */ + +/* {{{ php_xsl_set_object */ +void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC) +{ + xsl_object *object; + + object = (xsl_object *)zend_objects_get_address(wrapper TSRMLS_CC); + object->ptr = obj; + xsl_object_set_data(obj, wrapper TSRMLS_CC); +} +/* }}} */ + +/* {{{ php_xsl_create_object */ +zval *php_xsl_create_object(xsltStylesheetPtr obj, int *found, zval *wrapper_in, zval *return_value TSRMLS_DC) +{ + zval *wrapper; + zend_class_entry *ce; + + *found = 0; + + if (!obj) { + if(!wrapper_in) { + ALLOC_ZVAL(wrapper); + } else { + wrapper = wrapper_in; + } + ZVAL_NULL(wrapper); + return wrapper; + } + + if ((wrapper = (zval *) xsl_object_get_data((void *) obj))) { + zval_add_ref(&wrapper); + *found = 1; + return wrapper; + } + + if(!wrapper_in) { + wrapper = return_value; + } else { + wrapper = wrapper_in; + } + + + ce = xsl_xsltprocessor_class_entry; + + if(!wrapper_in) { + object_init_ex(wrapper, ce); + } + php_xsl_set_object(wrapper, (void *) obj TSRMLS_CC); + return (wrapper); +} +/* }}} */ + + + + +/* {{{ PHP_MSHUTDOWN_FUNCTION + */ +PHP_MSHUTDOWN_FUNCTION(xsl) +{ + /* uncomment this line if you have INI entries + UNREGISTER_INI_ENTRIES(); + */ + xsltCleanupGlobals(); + + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request start */ +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(xsl) +{ + return SUCCESS; +} +/* }}} */ + +/* Remove if there's nothing to do at request end */ +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(xsl) +{ + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(xsl) +{ + php_info_print_table_start(); + php_info_print_table_row(2, "XML/XSLT", "enabled"); + { + char buffer[128]; + int major, minor, subminor; + + php_info_print_table_row(2, "DOM/XSLT", "enabled"); + major = xsltLibxsltVersion/10000; + minor = (xsltLibxsltVersion - major * 10000) / 100; + subminor = (xsltLibxsltVersion - major * 10000 - minor * 100); + snprintf(buffer, 128, "%d.%d.%d", major, minor, subminor); + php_info_print_table_row(2, "libxslt Version", buffer); + major = xsltLibxmlVersion/10000; + minor = (xsltLibxmlVersion - major * 10000) / 100; + subminor = (xsltLibxmlVersion - major * 10000 - minor * 100); + snprintf(buffer, 128, "%d.%d.%d", major, minor, subminor); + php_info_print_table_row(2, "libxslt compiled against libxml Version", buffer); + } + php_info_print_table_end(); + + /* Remove comments if you have entries in php.ini + DISPLAY_INI_ENTRIES(); + */ +} +/* }}} */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/xsl/php_xsl.h b/ext/xsl/php_xsl.h new file mode 100644 index 0000000000..2362fb3052 --- /dev/null +++ b/ext/xsl/php_xsl.h @@ -0,0 +1,113 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef PHP_XSL_H +#define PHP_XSL_H + +extern zend_module_entry xsl_module_entry; +#define phpext_xsl_ptr &xsl_module_entry + +#ifdef PHP_WIN32 +#define PHP_XSL_API __declspec(dllexport) +#else +#define PHP_XSL_API +#endif + +#ifdef ZTS +#include "TSRM.h" +#endif + +#include +#include +#include +#include + +#include "../dom/xml_common.h" +#include "xsl_fe.h" + +typedef struct _xsl_object { + zend_object std; + void *ptr; + HashTable *prop_handler; + node_list_pointer *node_list; + HashTable *parameter; +} xsl_object; + +void php_xsl_set_object(zval *wrapper, void *obj TSRMLS_DC); +void xsl_objects_dtor(void *object, zend_object_handle handle TSRMLS_DC); +zval *php_xsl_create_object(xsltStylesheetPtr obj, int *found, zval *wrapper_in, zval *return_value TSRMLS_DC); + +#define REGISTER_XSL_CLASS(ce, name, parent_ce, funcs, entry) \ +INIT_CLASS_ENTRY(ce, name, funcs); \ +ce.create_object = xsl_objects_new; \ +entry = zend_register_internal_class_ex(&ce, parent_ce, NULL TSRMLS_CC); + +#define XSL_DOMOBJ_NEW(zval, obj, ret) \ + if (NULL == (zval = php_xsl_create_object(obj, ret, zval, return_value TSRMLS_CC))) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object"); \ + RETURN_FALSE; \ + } + + + +PHP_MINIT_FUNCTION(xsl); +PHP_MSHUTDOWN_FUNCTION(xsl); +PHP_RINIT_FUNCTION(xsl); +PHP_RSHUTDOWN_FUNCTION(xsl); +PHP_MINFO_FUNCTION(xsl); + + +/* + Declare any global variables you may need between the BEGIN + and END macros here: + +ZEND_BEGIN_MODULE_GLOBALS(xsl) + long global_value; + char *global_string; +ZEND_END_MODULE_GLOBALS(xsl) +*/ + +/* In every utility function you add that needs to use variables + in php_xsl_globals, call TSRM_FETCH(); after declaring other + variables used by that function, or better yet, pass in TSRMLS_CC + after the last function argument and declare your utility function + with TSRMLS_DC after the last declared argument. Always refer to + the globals in your function as XSL_G(variable). You are + encouraged to rename these macros something shorter, see + examples in any other php module directory. +*/ + +#ifdef ZTS +#define XSL_G(v) TSRMG(xsl_globals_id, zend_xsl_globals *, v) +#else +#define XSL_G(v) (xsl_globals.v) +#endif + +#endif /* PHP_XSL_H */ + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/ext/xsl/xsl.dsp b/ext/xsl/xsl.dsp new file mode 100644 index 0000000000..f93a73d402 --- /dev/null +++ b/ext/xsl/xsl.dsp @@ -0,0 +1,118 @@ +# Microsoft Developer Studio Project File - Name="xsl" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=xsl - Win32 Debug_TS +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "xsl.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "xsl.mak" CFG="xsl - Win32 Debug_TS" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "xsl - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "xsl - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "xsl - Win32 Release_TS" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release_TS" +# PROP BASE Intermediate_Dir "Release_TS" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release_TS" +# PROP Intermediate_Dir "Release_TS" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XSL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XSL_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 + +!ELSEIF "$(CFG)" == "xsl - Win32 Debug_TS" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug_TS" +# PROP BASE Intermediate_Dir "Debug_TS" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug_TS" +# PROP Intermediate_Dir "Debug_TS" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XSL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "XSL_EXPORTS" /D "COMPILE_DL_XSL" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D LIBXML_STATIC=1 /D LIBXSLT_STATIC=1 /FR /YX /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x406 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 php4ts_debug.lib php_dom.lib libxml2_a.lib libxslt_a.lib iconv.lib resolv.lib kernel32.lib user32.lib gdi32.lib winspool.lib /nologo /dll /debug /machine:I386 /nodefaultlib:"msvcrt" /out:"..\..\Debug_TS/php_xsl.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\bindlib_w32\Release" /libpath:"..\..\..\php_build\lib\libxslt" /libpath:"..\domxml5\debug_ts" + +!ENDIF + +# Begin Target + +# Name "xsl - Win32 Release_TS" +# Name "xsl - Win32 Debug_TS" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\php_xsl.c +# End Source File +# Begin Source File + +SOURCE=.\xsltprocessor.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\php_xsl.h +# End Source File +# Begin Source File + +SOURCE=.\xsl_fe.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/ext/xsl/xsl_fe.h b/ext/xsl/xsl_fe.h new file mode 100644 index 0000000000..39a84910c9 --- /dev/null +++ b/ext/xsl/xsl_fe.h @@ -0,0 +1,12 @@ + + +extern zend_function_entry php_xsl_xsltprocessor_class_functions[]; +zend_class_entry *xsl_xsltprocessor_class_entry; + +PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet); +PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc); +PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri); +PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml); +PHP_FUNCTION(xsl_xsltprocessor_set_parameter); +PHP_FUNCTION(xsl_xsltprocessor_get_parameter); +PHP_FUNCTION(xsl_xsltprocessor_remove_parameter); diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c new file mode 100644 index 0000000000..7b3f4a560a --- /dev/null +++ b/ext/xsl/xsltprocessor.c @@ -0,0 +1,325 @@ +/* + +----------------------------------------------------------------------+ + | PHP Version 4 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2003 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.02 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.php.net/license/2_02.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Christian Stocker | + | Rob Richards | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "php.h" +#include "php_xsl.h" + + +/* +* class xsl_xsltprocessor +* +* URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# +* Since: +*/ + +zend_function_entry php_xsl_xsltprocessor_class_functions[] = { + PHP_FALIAS(import_stylesheet, xsl_xsltprocessor_import_stylesheet, NULL) + PHP_FALIAS(transform_to_doc, xsl_xsltprocessor_transform_to_doc, NULL) + PHP_FALIAS(transform_to_uri, xsl_xsltprocessor_transform_to_uri, NULL) + PHP_FALIAS(transform_to_xml, xsl_xsltprocessor_transform_to_xml, NULL) + PHP_FALIAS(set_parameter, xsl_xsltprocessor_set_parameter, NULL) + PHP_FALIAS(get_parameter, xsl_xsltprocessor_get_parameter, NULL) + PHP_FALIAS(remove_parameter, xsl_xsltprocessor_remove_parameter, NULL) + {NULL, NULL, NULL} +}; + +/* {{{ attribute protos, not implemented yet */ +/* {{{ php_xsl_xslt_string_to_xpathexpr() + Translates a string to a XPath Expression */ +static char *php_xsl_xslt_string_to_xpathexpr(const char *str TSRMLS_DC) +{ + const xmlChar *string = (const xmlChar *)str; + + xmlChar *value; + int str_len; + + str_len = xmlStrlen(string) + 3; + + if (xmlStrchr(string, '"')) { + if (xmlStrchr(string, '\'')) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create XPath expression (string contains both quote and double-quotes)"); + return NULL; + } + value = (xmlChar*) emalloc (str_len * sizeof(xmlChar) ); + snprintf(value, str_len, "'%s'", string); + } else { + value = (xmlChar*) emalloc (str_len * sizeof(xmlChar) ); + snprintf(value, str_len, "\"%s\"", string); + } + return (char *) value; +} + +/* {{{ php_xsl_xslt_make_params() + Translates a PHP array to a libxslt parameters array */ +static char **php_xsl_xslt_make_params(HashTable *parht, int xpath_params TSRMLS_DC) +{ + + int parsize; + zval **value; + char *xpath_expr, *string_key = NULL; + ulong num_key; + char **params = NULL; + int i = 0; + + parsize = (2 * zend_hash_num_elements(parht) + 1) * sizeof(char *); + params = (char **)emalloc(parsize); + memset((char *)params, 0, parsize); + + for (zend_hash_internal_pointer_reset(parht); + zend_hash_get_current_data(parht, (void **)&value) == SUCCESS; + zend_hash_move_forward(parht)) { + + if (zend_hash_get_current_key(parht, &string_key, &num_key, 1) != HASH_KEY_IS_STRING) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument or parameter array"); + return NULL; + } else { + SEPARATE_ZVAL(value); + convert_to_string_ex(value); + + if (!xpath_params) { + xpath_expr = php_xsl_xslt_string_to_xpathexpr(Z_STRVAL_PP(value) TSRMLS_CC); + } else { + xpath_expr = Z_STRVAL_PP(value); + } + if (xpath_expr) { + params[i++] = string_key; + params[i++] = xpath_expr; + } + } + } + + params[i++] = NULL; + + return params; +} +/* }}} */ +/* {{{ proto xsl_xsltdocucument xsl_xsltprocessor_import_stylesheet(node index); +URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# +Since: +*/ +PHP_FUNCTION(xsl_xsltprocessor_import_stylesheet) +{ + zval *id, *docp = NULL; + xmlDoc *doc; + xsltStylesheetPtr sheetp, oldsheetp; + xmlDocPtr newdocp; + xsl_object *intern; + + DOM_GET_THIS(id); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) { + RETURN_FALSE; + } + DOM_GET_OBJ(doc, docp, xmlDocPtr); + /* copy the doc, so that it's not accessable from outside + FIXME: and doubling memory consumption... + */ + newdocp = xmlCopyDoc(doc, 1); + sheetp = xsltParseStylesheetDoc(newdocp); + + if (!sheetp) { + xmlFreeDoc(newdocp); + RETURN_FALSE; + } + + intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); + if ((oldsheetp = (xsltStylesheetPtr)intern->ptr)) { + /* free wrapper */ + if (((xsltStylesheetPtr) intern->ptr)->_private != NULL) { + efree(((xsltStylesheetPtr) intern->ptr)->_private); + ((xsltStylesheetPtr) intern->ptr)->_private = NULL; + } + //FIXME: more non-thread safe stuff + xsltFreeStylesheet((xsltStylesheetPtr) intern->ptr); + intern->ptr = NULL; + } + php_xsl_set_object(id, sheetp TSRMLS_CC); +} +/* }}} end xsl_xsltprocessor_import_stylesheet */ + + +/* {{{ proto xsl_document xsl_xsltprocessor_transform_to_doc(node doc); +URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html# +Since: +*/ +PHP_FUNCTION(xsl_xsltprocessor_transform_to_doc) +{ + zval *id, *rv = NULL, *docp = NULL; + xmlDoc *doc; + xmlDoc *newdocp; + xsltStylesheetPtr sheetp; + int ret; + char **params = NULL; + xsl_object *intern; + + DOM_GET_THIS_OBJ(sheetp, id, xsltStylesheetPtr); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) { + RETURN_FALSE; + } + DOM_GET_OBJ(doc, docp, xmlDocPtr); + intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); + if (intern->parameter) { + params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC); + } + newdocp = xsltApplyStylesheet(sheetp, doc, (const char**) params); + + if (params) { + efree(params); + } + + if (newdocp) { + DOM_RET_OBJ(rv, (xmlNodePtr) newdocp, &ret); + } else { + RETURN_FALSE; + } + +} +/* }}} end xsl_xsltprocessor_transform_to_doc */ + + +/* {{{ proto xsl_ xsl_xsltprocessor_transform_to_uri(node doc, string uri); +*/ +PHP_FUNCTION(xsl_xsltprocessor_transform_to_uri) +{ + DOM_NOT_IMPLEMENTED(); +} +/* }}} end xsl_xsltprocessor_transform_to_uri */ + + +/* {{{ proto xsl_string xsl_xsltprocessor_transform_to_xml(node doc); +*/ +PHP_FUNCTION(xsl_xsltprocessor_transform_to_xml) +{ + zval *id, *docp = NULL; + xmlDoc *doc; + xmlDoc *newdocp; + xsltStylesheetPtr sheetp; + int ret; + xmlChar *doc_txt_ptr; + int doc_txt_len; + char **params = NULL; + xsl_object *intern; + + DOM_GET_THIS_OBJ(sheetp, id, xsltStylesheetPtr); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &docp) == FAILURE) { + RETURN_FALSE; + } + DOM_GET_OBJ(doc, docp, xmlDocPtr); + intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); + if (intern->parameter) { + params = php_xsl_xslt_make_params(intern->parameter, 0 TSRMLS_CC); + } + newdocp = xsltApplyStylesheet(sheetp, doc, (const char**)params); + + if (params) { + efree(params); + } + ret = xsltSaveResultToString(&doc_txt_ptr, &doc_txt_len, newdocp, sheetp); + + if (ret < 0) { + RETURN_FALSE; + } + + RETVAL_STRINGL(doc_txt_ptr, doc_txt_len, 1); + xmlFree(doc_txt_ptr); + xmlFreeDoc(newdocp); +} +/* }}} end xsl_xsltprocessor_transform_to_xml */ + + +/* {{{ proto xsl_ xsl_xsltprocessor_set_parameter(string namespace, string name, string value); +*/ +PHP_FUNCTION(xsl_xsltprocessor_set_parameter) +{ + + zval *id; + int name_len = 0, namespace_len = 0, value_len = 0; + char *name, *namespace, *value; + xsl_object *intern; + zval *new_string; + + DOM_GET_THIS(id); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &namespace, &namespace_len, &name, &name_len, &value, &value_len) == FAILURE) { + RETURN_FALSE; + } + intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); + + + MAKE_STD_ZVAL(new_string); + ZVAL_STRING(new_string, value, 1); + zend_hash_update(intern->parameter, name, name_len + 1, &new_string, sizeof(zval*), NULL); +} +/* }}} end xsl_xsltprocessor_set_parameter */ + +/* {{{ proto xsl_ xsl_xsltprocessor_get_parameter(string namespace, string name); +*/ +PHP_FUNCTION(xsl_xsltprocessor_get_parameter) +{ + zval *id; + int name_len = 0, namespace_len = 0; + char *name, *namespace; + zval **value; + xsl_object *intern; + + DOM_GET_THIS(id); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) { + RETURN_FALSE; + } + intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); + if ( zend_hash_find(intern->parameter, name, name_len + 1, (void**) &value) == SUCCESS) { + convert_to_string_ex(value); + RETVAL_STRING(Z_STRVAL_PP(value),1); + } else { + RETURN_FALSE; + } +} +/* }}} end xsl_xsltprocessor_get_parameter */ + +/* {{{ proto xsl_ xsl_xsltprocessor_remove_parameter(string namespace, string name); +*/ +PHP_FUNCTION(xsl_xsltprocessor_remove_parameter) +{ + zval *id; + int name_len = 0, namespace_len = 0; + char *name, *namespace; + xsl_object *intern; + + DOM_GET_THIS(id); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &namespace, &namespace_len, &name, &name_len) == FAILURE) { + RETURN_FALSE; + } + intern = (xsl_object *)zend_object_store_get_object(id TSRMLS_CC); + if ( zend_hash_del(intern->parameter, name, name_len + 1) == SUCCESS) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} end xsl_xsltprocessor_remove_parameter */