📄 sablot.c
字号:
/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2007 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.php.net/license/3_01.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: Sterling Hughes <sterling@php.net> | | David Viner <dviner@php.net> | | Lenar Lohmus <flex@php.net> | | Melvyn Sopacua <msopacua@php.net> | +----------------------------------------------------------------------+ *//* $Id: sablot.c,v 1.68.2.4.4.2 2007/01/01 09:46:49 sebastian Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "php_xslt.h"#include "php_sablot.h"#include "ext/standard/info.h"#if HAVE_SABLOT_BACKEND#ifdef HAVE_SABLOT_CONFIG#include "php_sab_info.h"#endif#include <sablot.h>#include <string.h>#include <stdarg.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>/* functions relating to handlers */static void register_sax_handler_pair(zval **, zval **, zval ** TSRMLS_DC);/* Free processor */static void free_processor(zend_rsrc_list_entry *rsrc TSRMLS_DC);/* Scheme handler functions */static int scheme_getall(void *, SablotHandle, const char *, const char *, char **, int *);static int scheme_freememory(void *, SablotHandle, char *);static int scheme_open(void *, SablotHandle, const char *, const char *, int *);static int scheme_get(void *, SablotHandle, int, char *, int *);static int scheme_put(void *, SablotHandle, int, const char *, int *);static int scheme_close(void *, SablotHandle, int);/* Sax handler functions */static SAX_RETURN sax_startdoc(void *, SablotHandle);static SAX_RETURN sax_startelement(void *, SablotHandle, const char *, const char **);static SAX_RETURN sax_endelement(void *, SablotHandle, const char *);static SAX_RETURN sax_startnamespace(void *, SablotHandle, const char *, const char *);static SAX_RETURN sax_endnamespace(void *, SablotHandle, const char *);static SAX_RETURN sax_comment(void *, SablotHandle, const char *);static SAX_RETURN sax_pi(void *, SablotHandle, const char *, const char *);static SAX_RETURN sax_characters(void *, SablotHandle, const char *, int);static SAX_RETURN sax_enddoc(void *, SablotHandle);/* Error handlers */static MH_ERROR error_makecode(void *, SablotHandle, int, unsigned short, unsigned short);static MH_ERROR error_log(void *, SablotHandle, MH_ERROR, MH_LEVEL, char **);static MH_ERROR error_print(void *, SablotHandle, MH_ERROR, MH_LEVEL, char **);/* Resource related */#define le_xslt_name "XSLT Processor"static int le_xslt;/* {{{ xslt_functions[] */static unsigned char second_args_force_ref[] = { 2, BYREF_NONE, BYREF_FORCE };function_entry xslt_functions[] = { PHP_FE(xslt_create, NULL) PHP_FE(xslt_set_sax_handlers, NULL) PHP_FE(xslt_set_scheme_handlers, NULL) PHP_FE(xslt_set_error_handler, NULL) PHP_FE(xslt_set_base, NULL)#ifdef HAVE_SABLOT_SET_ENCODING PHP_FE(xslt_set_encoding, NULL)#endif PHP_FE(xslt_set_log, NULL) PHP_FE(xslt_process, NULL) PHP_FE(xslt_error, NULL) PHP_FE(xslt_errno, NULL) PHP_FE(xslt_free, NULL) PHP_FE(xslt_set_object, second_args_force_ref) PHP_FE(xslt_setopt, NULL)#ifdef HAVE_SABLOT_GET_OPTIONS PHP_FE(xslt_getopt, NULL)#endif PHP_FE(xslt_backend_version, NULL) PHP_FE(xslt_backend_name, NULL) PHP_FE(xslt_backend_info, NULL) {NULL, NULL, NULL}};/* }}} *//* {{{ xslt_module_entry */zend_module_entry xslt_module_entry = { STANDARD_MODULE_HEADER, "xslt", xslt_functions, PHP_MINIT(xslt), NULL, NULL, NULL, PHP_MINFO(xslt), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES};/* }}} */#ifdef COMPILE_DL_XSLTZEND_GET_MODULE(xslt)#endif/* {{{ handler structs A structure containing the sax handlers, automatically registered whether the user defines them or not */static SAXHandler sax_handlers = { sax_startdoc, sax_startelement, sax_endelement, sax_startnamespace, sax_endnamespace, sax_comment, sax_pi, sax_characters, sax_enddoc};/* Error handlers, automatically registered */static MessageHandler message_handler = { error_makecode, error_log, error_print};/* Scheme handlers automatically registered */static SchemeHandler scheme_handler = { scheme_getall, scheme_freememory, scheme_open, scheme_get, scheme_put, scheme_close};/* }}} *//* {{{ PHP_MINIT_FUNCTION */PHP_MINIT_FUNCTION(xslt){ le_xslt = zend_register_list_destructors_ex(free_processor, NULL, le_xslt_name, module_number); /* Generic options, which can apply to 'all' xslt processors */ REGISTER_LONG_CONSTANT("XSLT_OPT_SILENT", SAB_NO_ERROR_REPORTING, CONST_CS | CONST_PERSISTENT); /* Error constants, which are useful in userspace. */ REGISTER_LONG_CONSTANT("XSLT_ERR_UNSUPPORTED_SCHEME", SH_ERR_UNSUPPORTED_SCHEME, CONST_CS | CONST_PERSISTENT); /* Sablotron specific options */ REGISTER_LONG_CONSTANT("XSLT_SABOPT_PARSE_PUBLIC_ENTITIES", SAB_PARSE_PUBLIC_ENTITIES, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSLT_SABOPT_DISABLE_ADDING_META", SAB_DISABLE_ADDING_META, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSLT_SABOPT_DISABLE_STRIPPING", SAB_DISABLE_STRIPPING, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("XSLT_SABOPT_IGNORE_DOC_NOT_FOUND", SAB_IGNORE_DOC_NOT_FOUND, CONST_CS | CONST_PERSISTENT);/* hack: implemented at the same time, so should work. Otherwise we need to check the enum type of SablotFlag in <sablot.h> */#ifdef HAVE_SABLOT_GET_OPTIONS REGISTER_LONG_CONSTANT("XSLT_SABOPT_FILES_TO_HANDLER", SAB_FILES_TO_HANDLER, CONST_CS | CONST_PERSISTENT);#endif return SUCCESS;}/* }}} *//* {{{ PHP_MINFO_FUNCTION */PHP_MINFO_FUNCTION(xslt){ php_info_print_table_start(); php_info_print_table_row(2, "XSLT support", "enabled"); php_info_print_table_row(2, "Backend", "Sablotron");#ifdef SAB_VERSION php_info_print_table_row(2, "Sablotron Version", SAB_VERSION);#endif#ifdef HAVE_SABLOT_CONFIG php_info_print_table_row(2, "Sablotron Information", SAB_INFO);#endif php_info_print_table_end();}/* }}} *//* {{{ proto resource xslt_create(void) Create a new XSLT processor */PHP_FUNCTION(xslt_create){ php_xslt *handle; /* The php -> sablotron handle */ SablotHandle processor; /* The sablotron processor */ SablotSituation sit; /* The sablotron Situation handle */ int error; /* The error container */ /* Allocate the php-sablotron handle */ handle = ecalloc(1, sizeof(php_xslt)); handle->handlers = ecalloc(1, sizeof(struct xslt_handlers)); handle->err = ecalloc(1, sizeof(struct xslt_error)); handle->object = NULL; handle->base_isset = 0; XSLT_LOG(handle).path = NULL; /* Allocate the actual processor itself, via sablotron */ SablotCreateSituation(&sit); error = SablotCreateProcessorForSituation(sit, &processor); if (error) { XSLT_ERRNO(handle) = error; RETURN_FALSE; } /* Save the processor and set the default handlers */ XSLT_PROCESSOR(handle) = processor; XSLT_SITUATION(handle) = sit; SablotRegHandler(XSLT_PROCESSOR(handle), HLR_SAX, (void *) &sax_handlers, (void *) handle); SablotRegHandler(XSLT_PROCESSOR(handle), HLR_MESSAGE, (void *) &message_handler, (void *) handle); SablotRegHandler(XSLT_PROCESSOR(handle), HLR_SCHEME, (void *) &scheme_handler, (void *) handle); /* Register the processor as a resource and return it to the user */ ZEND_REGISTER_RESOURCE(return_value, handle, le_xslt); /* The resource index, save it for later use */ handle->processor.idx = Z_LVAL_P(return_value);}/* }}} *//* {{{ proto void xslt_set_sax_handlers(resource processor, array handlers) Set the SAX handlers to be called when the XML document gets processed */PHP_FUNCTION(xslt_set_sax_handlers){ zval **processor_p, /* Resource pointer to the php->sablotron handle */ **sax_handlers_p, /* Pointer to the sax handlers php array */ **handler; /* Individual handler, or handler pair */ HashTable *sax_handlers; /* PHP array of sax handlers */ php_xslt *handle; /* Pointer to a php_xslt handle */ char *string_key; /* String key for the hash */ ulong num_key; /* (unused) hash's numerical key */ int key_type; /* The type of the current hash key */ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &processor_p, &sax_handlers_p) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(handle, php_xslt *, processor_p, -1, le_xslt_name, le_xslt); /* Convert the sax_handlers_p zval ** to a hash table we can process */ sax_handlers = HASH_OF(*sax_handlers_p); if (!sax_handlers) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expecting an array as the second argument"); return; } /* Loop through the HashTable containing the SAX handlers */ for (zend_hash_internal_pointer_reset(sax_handlers); zend_hash_get_current_data(sax_handlers, (void **) &handler) == SUCCESS; zend_hash_move_forward(sax_handlers)) { key_type = zend_hash_get_current_key(sax_handlers, &string_key, &num_key, 0); if (key_type == HASH_KEY_IS_LONG) { convert_to_string_ex(handler); php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Skipping numerical index %ld (with value %s)", num_key, Z_STRVAL_PP(handler)); continue; } /* Document handlers (document start, document end) */ if (strcasecmp(string_key, "document") == 0) { SEPARATE_ZVAL(handler); register_sax_handler_pair(&XSLT_SAX(handle).doc_start, &XSLT_SAX(handle).doc_end, handler TSRMLS_CC); } /* Element handlers, start of an element, and end of an element */ else if (strcasecmp(string_key, "element") == 0) { SEPARATE_ZVAL(handler); register_sax_handler_pair(&XSLT_SAX(handle).element_start, &XSLT_SAX(handle).element_end, handler TSRMLS_CC); } /* Namespace handlers, start of a namespace, end of a namespace */ else if (strcasecmp(string_key, "namespace") == 0) { SEPARATE_ZVAL(handler); register_sax_handler_pair(&XSLT_SAX(handle).namespace_start, &XSLT_SAX(handle).namespace_end, handler TSRMLS_CC); } /* Comment handlers, called when a comment is reached */ else if (strcasecmp(string_key, "comment") == 0) { XSLT_SAX(handle).comment = *handler; zval_add_ref(&XSLT_SAX(handle).comment); } /* Processing instructions handler called when processing instructions (<? ?>) */ else if (strcasecmp(string_key, "pi") == 0) { XSLT_SAX(handle).pi = *handler; zval_add_ref(&XSLT_SAX(handle).pi); } /* Character handler, called when data is found */ else if (strcasecmp(string_key, "character") == 0) { XSLT_SAX(handle).characters = *handler; zval_add_ref(&XSLT_SAX(handle).characters); } /* Invalid handler name, tsk, tsk, tsk :) */ else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option: %s", string_key); } }}/* }}} *//* {{{ proto void xslt_set_scheme_handlers(resource processor, array handlers) Set the scheme handlers for the XSLT processor */PHP_FUNCTION(xslt_set_scheme_handlers){ zval **processor_p, /* Resource pointer to the php->sablotron handle */ **scheme_handlers_p, /* Pointer to the scheme handler array */ **handler; /* Individual scheme handler */ zval **assign_handle; /* The handler to assign to */ HashTable *scheme_handlers; /* Scheme handler array */ php_xslt *handle; /* php->sablotron handle */ char *string_key; /* Hash key (string) */ ulong num_key; /* (unused) Hash key (number) */ int key_type; /* The type of the current key */ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &processor_p, &scheme_handlers_p) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(handle, php_xslt *, processor_p, -1, le_xslt_name, le_xslt); scheme_handlers = HASH_OF(*scheme_handlers_p); if (!scheme_handlers) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "2nd argument must be an array"); return; } /* Loop through the scheme handlers array, setting the given scheme handlers */ for (zend_hash_internal_pointer_reset(scheme_handlers); zend_hash_get_current_data(scheme_handlers, (void **) &handler) == SUCCESS; zend_hash_move_forward(scheme_handlers)) { key_type = zend_hash_get_current_key(scheme_handlers, &string_key, &num_key, 0); if (key_type == HASH_KEY_IS_LONG) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Numerical key %ld (with value %s) being ignored", num_key, Z_STRVAL_PP(handler)); continue; } /* Open the URI and return the whole string */ if (strcasecmp(string_key, "get_all") == 0) { assign_handle = &XSLT_SCHEME(handle).sh_get_all; } /* Open the URI and return a handle */ else if (strcasecmp(string_key, "open") == 0) { assign_handle = &XSLT_SCHEME(handle).sh_open; } /* Retrieve data from the URI */ else if (strcasecmp(string_key, "get") == 0) { assign_handle = &XSLT_SCHEME(handle).sh_get; } /* Save data to the URI */ else if (strcasecmp(string_key, "put") == 0) { assign_handle = &XSLT_SCHEME(handle).sh_put; } /* Close the URI */ else if (strcasecmp(string_key, "close") == 0) { assign_handle = &XSLT_SCHEME(handle).sh_close; } /* Invalid handler name */ else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid option '%s', skipping", string_key); continue; } *assign_handle = *handler; zval_add_ref(assign_handle); }}/* }}} *//* {{{ proto void xslt_set_error_handler(resource processor, mixed error_func) Set the error handler, to be called when an XSLT error happens */PHP_FUNCTION(xslt_set_error_handler){ zval **processor_p, /* Resource Pointer to a PHP-XSLT processor */ **error_func; /* Name of the user defined error function */ php_xslt *handle; /* A PHP-XSLT processor */ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &processor_p, &error_func) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(handle, php_xslt *, processor_p, -1, le_xslt_name, le_xslt); XSLT_ERROR(handle) = *error_func; zval_add_ref(&XSLT_ERROR(handle));}/* }}} *//* {{{ proto void xslt_set_base(resource processor, string base) Sets the base URI for all XSLT transformations */PHP_FUNCTION(xslt_set_base){ zval **processor_p, /* Resource Pointer to a PHP-XSLT processor */ **base; /* The base URI for the transformation */ php_xslt *handle; /* A PHP-XSLT processor */ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &processor_p, &base) == FAILURE) { WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(handle, php_xslt *, processor_p, -1, le_xslt_name, le_xslt); convert_to_string_ex(base); /* Set the base */ SablotSetBase(XSLT_PROCESSOR(handle), Z_STRVAL_PP(base)); XSLT_BASE_ISSET(handle) = 1;}/* }}} *//* {{{ proto void xslt_set_encoding(resource processor, string encoding) Set the output encoding for the current stylesheet */PHP_FUNCTION(xslt_set_encoding){/* The user has to explicitly compile sablotron with sablotron encoding functions in order for SablotSetEncoding to be enabled. config.m4 automatically checks for this... */#ifdef HAVE_SABLOT_SET_ENCODING zval **processor_p, /* Resource Pointer to a PHP-XSLT processor */ **encoding; /* The encoding to use for the output */ php_xslt *handle; /* A PHP-XSLT processor */ if (ZEND_NUM_ARGS() != 2 ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -