From 0a1f0ea22eccdc666df117f9b686ffaab231c149 Mon Sep 17 00:00:00 2001 From: Sterling Hughes Date: Tue, 21 Nov 2000 12:12:19 +0000 Subject: [PATCH] Major rework of the basic api which provides: - All Sablotron errors are now caught meaning nothing is ever outputted directly to the screen allowing you to catch all errors. - A mechanism is provided for you to have an error function which recieves all sablotron errors. - All of the basic functions re-use a single processor increasing performance (especially with high loads). - Added a bunch of comments, more to come (this way other people can easily modify my source). @ Added the xslt_set_error_handler() function to the Sablotron extension. @ (Sterling) @ Improved Sablotron's error handling system allowing you to catch all @ errors before they are outputted to the screen. (Sterling) --- ext/sablot/php_sablot.h | 53 +++- ext/sablot/sablot.c | 547 +++++++++++++++++++++++++++++----------- 2 files changed, 440 insertions(+), 160 deletions(-) diff --git a/ext/sablot/php_sablot.h b/ext/sablot/php_sablot.h index 3879965668..fff7ddab6c 100644 --- a/ext/sablot/php_sablot.h +++ b/ext/sablot/php_sablot.h @@ -32,34 +32,53 @@ extern zend_module_entry sablot_module_entry; #define PHP_SABLOT_API #endif +/* Module functions */ PHP_MINIT_FUNCTION(sablot); +PHP_MSHUTDOWN_FUNCTION(sablot); PHP_MINFO_FUNCTION(sablot); + +/* Output transformation functions */ PHP_FUNCTION(xslt_output_begintransform); PHP_FUNCTION(xslt_output_endtransform); + +/* Basic transformation functions */ PHP_FUNCTION(xslt_transform); PHP_FUNCTION(xslt_process); + +/* Advanced API transformation functions */ PHP_FUNCTION(xslt_create); PHP_FUNCTION(xslt_run); -PHP_FUNCTION(xslt_fetch_result); -PHP_FUNCTION(xslt_openlog); -PHP_FUNCTION(xslt_closelog); PHP_FUNCTION(xslt_set_sax_handler); +PHP_FUNCTION(xslt_set_error_handler); +PHP_FUNCTION(xslt_fetch_result); PHP_FUNCTION(xslt_free); + +/* Error Handling functions */ PHP_FUNCTION(xslt_error); PHP_FUNCTION(xslt_errno); +PHP_FUNCTION(xslt_openlog); +PHP_FUNCTION(xslt_closelog); +/* Sablotron error structure */ struct _php_sablot_error { char *key; char *value; struct _php_sablot_error *next; }; - typedef struct _php_sablot_error php_sablot_error; + +/* Sablotron Handle */ typedef struct { - long index; + + /* Error Handling */ + zval *errorHandler; + php_sablot_error *errors; + php_sablot_error errors_start; int last_errno; - php_sablot_error *errors, errors_start; + + /* SAX Handling */ + long index; zval *startDocHandler; zval *startElementHandler; zval *endElementHandler; @@ -69,37 +88,43 @@ typedef struct { zval *PIHandler; zval *charactersHandler; zval *endDocHandler; + + /* Sablotron Related */ SablotHandle p; + } php_sablot; + +/* Sablotron Globals */ typedef struct { - char *output_transform_file; - int le_sablot; - int last_errno; - int processor; + zval *errorHandler; + SablotHandle processor; + php_sablot_error *errors; + php_sablot_error errors_start; + char *output_transform_file; /* For output transformations */ + int last_errno; /* Global last_errno, if no handle is found */ } php_sablot_globals; #ifdef ZTS #define SABLOTG(v) (sablot_globals->v) #define SABLOTLS_FETCH() php_sablot_globals *sablot_globals = ts_resource(sablot_globals_id) +#define SABLOTG_HANDLE (*sablot_globals) #else #define SABLOTG(v) (sablot_globals.v) +#define SABLOTG_HANDLE sablot_globals #define SABLOTLS_FETCH() #endif #else - #define phpext_sablot_ptr NULL - #endif #endif - /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: - */ + */ \ No newline at end of file diff --git a/ext/sablot/sablot.c b/ext/sablot/sablot.c index 4833f37c72..d7b5ac3aff 100644 --- a/ext/sablot/sablot.c +++ b/ext/sablot/sablot.c @@ -31,6 +31,8 @@ #include "ext/standard/php_output.h" #include "php_sablot.h" +static int le_sablot; + /* Functions related to PHP's list handling */ static void _php_sablot_free_processor(zend_rsrc_list_entry *rsrc); @@ -50,27 +52,59 @@ static SAX_RETURN _php_sablot_sax_endDoc(void *); /* Error Handling Functions */ static MH_ERROR _php_sablot_make_code(void *, SablotHandle, int, unsigned short, unsigned short); static MH_ERROR _php_sablot_error(void *, SablotHandle, MH_ERROR, MH_LEVEL, char **); +static void _php_sablot_standard_error(php_sablot_error *, php_sablot_error, int, int); /* PHP Utility Functions */ static void _php_sablot_ht_char(HashTable *, char **); static zval *_php_sablot_string_zval(const char *); static zval *_php_sablot_resource_zval(long); +/* Macro's */ + /* Free macros */ #define S_FREE(__var) if (__var) efree(__var); #define FUNCH_FREE(__var) if (__var) zval_del_ref(&(__var)); -/* ERROR Macro */ -#define SEND_ERROR_INFO(__error, __errlevel) \ - php_printf("A %s has occurred, sending all relevant information\n", __error); \ - handle->errors = handle->errors_start.next; \ - while (handle->errors) { \ - php_printf("%s: %s\n", handle->errors->key, handle->errors->value); \ - handle->errors = handle->errors->next; \ - } \ - php_error(__errlevel, ""); - - +/* ERROR Macros */ + +#define SABLOT_FREE_ERROR_HANDLE(__handle) \ + if ((__handle).errors) { \ + (__handle).errors = (__handle).errors_start.next; \ + while ((__handle).errors) { \ + S_FREE((__handle).errors->key); \ + S_FREE((__handle).errors->value); \ + (__handle).errors = (__handle).errors->next; \ + } \ + S_FREE((__handle).errors); \ + } + + +/* Sablotron Basic Api macro's */ +#define SABLOT_BASIC_CREATE_PROCESSOR() \ + if (SABLOTG(processor) == NULL) { \ + int ret = 0; \ + \ + ret = SablotCreateProcessor(&SABLOTG(processor)); \ + if (ret) { \ + SABLOTG(last_errno) = ret; \ + return; \ + } \ + \ + ret = SablotRegHandler(SABLOTG(processor), HLR_MESSAGE, (void *)&mh, (void *)NULL); \ + if (ret) { \ + SABLOTG(last_errno) = ret; \ + return; \ + } \ + } + +#define SABLOT_BASIC_HANDLE SABLOTG(processor) + +/** + * SAX Handler structure, this defines the different functions to be + * called when Sablotron's internal expat parser reaches the + * different callbacks. These are the same as the functions which are + * defined for expat. + */ static SAXHandler sax = { _php_sablot_sax_startDoc, _php_sablot_sax_startElement, @@ -83,14 +117,17 @@ static SAXHandler sax = { _php_sablot_sax_endDoc }; + +/** + * Message Handler structure for use when Sablotron + * reports that something has gone wrong. + */ static MessageHandler mh = { _php_sablot_make_code, _php_sablot_error, _php_sablot_error }; -/* {{{ Begin PHP Extension code */ - #ifdef ZTS int sablot_globals_id; #else @@ -112,6 +149,7 @@ function_entry sablot_functions[] = { PHP_FE(xslt_openlog, NULL) PHP_FE(xslt_closelog, NULL) PHP_FE(xslt_set_sax_handler, NULL) + PHP_FE(xslt_set_error_handler, NULL) PHP_FE(xslt_free, NULL) PHP_FE(xslt_error, NULL) PHP_FE(xslt_errno, NULL) @@ -122,7 +160,7 @@ zend_module_entry sablot_module_entry = { "sablot", sablot_functions, PHP_MINIT(sablot), - NULL, + PHP_MSHUTDOWN(sablot), NULL, NULL, PHP_MINFO(sablot), @@ -133,37 +171,43 @@ zend_module_entry sablot_module_entry = { ZEND_GET_MODULE(sablot) #endif -/* }}} */ - -/* {{{ MINIT and MINFO Functions */ +/* MINIT and MINFO Functions */ PHP_MINIT_FUNCTION(sablot) { - SABLOTLS_FETCH(); - SABLOTG(le_sablot) = zend_register_list_destructors_ex(_php_sablot_free_processor, NULL, "sablotron", module_number); + le_sablot = zend_register_list_destructors_ex(_php_sablot_free_processor, NULL, "Sablotron XSLT", module_number); + return SUCCESS; } +PHP_MSHUTDOWN_FUNCTION(sablot) +{ + SABLOTLS_FETCH(); + + if (SABLOTG(processor)) { + SablotUnregHandler(SABLOTG(processor), HLR_MESSAGE, NULL, NULL); + SablotDestroyProcessor(SABLOTG(processor)); + } + + return SUCCESS; +} + PHP_MINFO_FUNCTION(sablot) { php_info_print_table_start(); - php_info_print_table_row(2, "Sablotron support", "enabled"); + php_info_print_table_row(2, "Sablotron XSLT support", "enabled"); php_info_print_table_end(); } -/* }}} */ - -/* }}} */ - -/* {{{ Begin Extension function */ - -/* {{{ Begin Output Transformation functions */ /* {{{ proto void xslt_output_begintransform(string file) Begin filtering of all data that is being printed out through the XSL file given by the file parameter. */ PHP_FUNCTION(xslt_output_begintransform) { + /* The name of the file to pass the output through */ zval **file; + + /* needed for the output transformation file name */ SABLOTLS_FETCH(); if (ZEND_NUM_ARGS() != 1 || @@ -172,9 +216,15 @@ PHP_FUNCTION(xslt_output_begintransform) } convert_to_string_ex(file); + /* If the buffer exists, free it */ S_FREE(SABLOTG(output_transform_file)); - + SABLOTG(output_transform_file) = estrndup(Z_STRVAL_PP(file), Z_STRLEN_PP(file)); + + /** + * Start output buffering, NULL signifies that no "user-space" output function + * will be used. + */ php_start_ob_buffer(NULL); } /* }}} */ @@ -186,45 +236,81 @@ PHP_FUNCTION(xslt_output_endtransform) char *tRes = NULL, *buffer = NULL; int ret = 0; + + /* Fetch both the output globals and the sablotron globals */ OLS_FETCH(); SABLOTLS_FETCH(); + /** + * Make sure that we don't have more than one output buffer going on + * at the same time. + */ if (OG(nesting_level) == 0) { RETURN_NULL(); } buffer = estrndup(OG(active_ob_buffer).buffer, OG(active_ob_buffer).text_length); + /* Nake sure there is data to send */ if (strlen(buffer)) { char *args[] = {"/_xmlinput", buffer, "/_output", NULL}; - ret = SablotProcess(SABLOTG(output_transform_file), "arg:/_xmlinput", "arg:/_output", NULL, args, &tRes); - } + SABLOT_BASIC_CREATE_PROCESSOR(); + + ret = SablotRunProcessor(SABLOT_BASIC_HANDLE, SABLOTG(output_transform_file), + "arg:/_xmlinput", "arg:/_output", NULL, args); + + if (ret) { + SABLOTG(last_errno) = ret; + S_FREE(SABLOTG(output_transform_file)); + RETURN_NULL(); + } + + ret = SablotGetResultArg(SABLOT_BASIC_HANDLE, "arg:/_output", &tRes); + + if (ret) { + SABLOTG(last_errno) = ret; + S_FREE(SABLOTG(output_transform_file)); + RETURN_NULL(); + } + } + /** + * A non-zero return means error, save this error in the global + * errno (for xslt_errno() and xslt_error()) free the output + * transformation file and null. + */ if (ret) { SABLOTG(last_errno) = ret; S_FREE(SABLOTG(output_transform_file)); - return; + RETURN_NULL(); } - - php_end_ob_buffer(0); + + /** + * If there is a buffer, end output buffering and clear the + * current output buffer (so we don't send data twice) + */ + if (tRes) + php_end_ob_buffer(0); PUTS(tRes); + S_FREE(SABLOTG(output_transform_file)); S_FREE(buffer); - if (tRes) { - SablotFree(tRes); - } else { - php_end_ob_buffer(0); - } + /** + * If there exists a result, free that result + * otherwise just end output buffering and send the + * data. + */ + if (tRes) + SablotFree(tRes); + else + php_end_ob_buffer(1); } /* }}} */ -/* }}} */ -/* {{{ Begin Simple API */ - /* {{{ proto bool xslt_transform(string xslt_uri, string transform_uri, string result_uri[, array xslt_params[, array xslt_args[, string &result]]]) Transform an XML document, transform_uri, with an XSL stylesheet, xslt_uri with parameters, xslt_params, into the Result buffer, result_uri, xslt_args defines the variables in xslt_uri, transform_uri and result_uri. */ PHP_FUNCTION(xslt_transform) @@ -235,11 +321,14 @@ PHP_FUNCTION(xslt_transform) **xslt_params, **xslt_args, **result; + char **args = NULL, **params = NULL, *tResult = NULL; + int argc = ZEND_NUM_ARGS(), ret = 0; + SABLOTLS_FETCH(); if (argc < 3 || argc > 6 || @@ -248,24 +337,45 @@ PHP_FUNCTION(xslt_transform) } multi_convert_to_string_ex(3, xslt_uri, transform_uri, result_uri); + /** + * if there are more than 3 function arguments, inspect the value of + * the third argument and decide whether or not there are Sablotron + * parameters. + */ if (argc > 3) { - if (Z_TYPE_PP(xslt_params) != IS_LONG || Z_LVAL_PP(xslt_params) != 0) { + if (Z_TYPE_PP(xslt_params) != IS_LONG || Z_LVAL_PP(xslt_params) != 0 || + Z_TYPE_PP(xslt_params) != IS_NULL) { int numelems, size; HashTable *ar = HASH_OF(*xslt_params); + /** + * Allocate 2 times the number of elements in + * the array, since with associative arrays in PHP + * keys are not counted. + */ numelems = zend_hash_num_elements(ar); size = (numelems * 2 + 1) * sizeof(char *); params = (char **)emalloc(size+1); memset((char *)params, 0, size); + /** + * Translate a PHP array (HashTable *) into a + * Sablotron array (char **). + */ _php_sablot_ht_char(ar, params); } } + /** + * If there are more than 4 function arguments, inspect the value + * of the 4 argument and decide whether or not there are Sablotron + * arguments. + */ if (argc > 4) { - if (Z_TYPE_PP(xslt_args) != IS_LONG || Z_LVAL_PP(xslt_args) != 0) { + if (Z_TYPE_PP(xslt_args) != IS_LONG || Z_LVAL_PP(xslt_args) != 0 || + Z_TYPE_PP(xslt_args) != IS_NULL) { int numelems, size; HashTable *ar = HASH_OF(*xslt_args); @@ -280,21 +390,33 @@ PHP_FUNCTION(xslt_transform) } } - ret = SablotProcess(Z_STRVAL_PP(xslt_uri), Z_STRVAL_PP(transform_uri), - Z_STRVAL_PP(result_uri), params, args, &tResult); - + SABLOT_BASIC_CREATE_PROCESSOR(); + ret = SablotRunProcessor(SABLOT_BASIC_HANDLE, Z_STRVAL_PP(xslt_uri), + Z_STRVAL_PP(transform_uri), Z_STRVAL_PP(result_uri), + params, args); + if (ret) { SABLOTG(last_errno) = ret; S_FREE(params); S_FREE(args); - if (tResult) { - SablotFree(tResult); - } RETURN_FALSE; - } else { RETVAL_TRUE; } - + } + + ret = SablotGetResultArg(SABLOT_BASIC_HANDLE, Z_STRVAL_PP(result_uri), &tResult); + + if (ret) { + SABLOTG(last_errno) = ret; + + S_FREE(params); + S_FREE(args); + + if (tResult) + SablotFree(tResult); + + RETURN_FALSE; + } else { RETVAL_TRUE; } if (tResult && argc == 6) { @@ -327,22 +449,48 @@ PHP_FUNCTION(xslt_process) WRONG_PARAM_COUNT; } multi_convert_to_string_ex(2, xslt, input); - + + SABLOT_BASIC_CREATE_PROCESSOR(); + + /** + * If we have more than three arguments that means we have + * a base! + */ if (argc > 3) { - convert_to_string_ex(base); - ret = SablotProcessStringsWithBase(Z_STRVAL_PP(xslt), Z_STRVAL_PP(input), &tRes, Z_STRVAL_PP(base)); - } else { - ret = SablotProcessStrings(Z_STRVAL_PP(xslt), Z_STRVAL_PP(input), &tRes); + convert_to_string_ex(base); + + SablotSetBase(SABLOT_BASIC_HANDLE, Z_STRVAL_PP(base)); + } + + /** + * Need to declare args here (to lazy to actually allocate + * it with emalloc() ;) + */ + { + char *args[] = {"/_stylesheet", Z_STRVAL_PP(xslt), + "/_xmlinput", Z_STRVAL_PP(input), + "/_output", NULL, + NULL}; + + ret = SablotRunProcessor(SABLOT_BASIC_HANDLE, "arg:/_stylesheet", + "arg:/_xmlinput", "arg:/_output", + NULL, args); } if (ret) { - SABLOTG(last_errno) = ret; - if (tRes) { - SablotFree(tRes); - } - RETURN_FALSE; + SABLOTG(last_errno) = ret; + RETURN_FALSE; } - + + SablotGetResultArg(SABLOT_BASIC_HANDLE, "arg:/_output", &tRes); + if (ret) { + SABLOTG(last_errno) = ret; + RETURN_FALSE; + + if (tRes) + SablotFree(tRes); + } + if (tRes) { ZVAL_STRING(*result, tRes, 1); SablotFree(tRes); @@ -351,9 +499,6 @@ PHP_FUNCTION(xslt_process) } /* }}} */ -/* }}} */ - -/* {{{ Begin Advanced Resource API */ /* {{{ proto resource xslt_create(void) Create a new XSL processor and return a resource identifier. */ @@ -393,7 +538,7 @@ PHP_FUNCTION(xslt_create) RETURN_FALSE; } - ZEND_REGISTER_RESOURCE(return_value, handle, SABLOTG(le_sablot)); + ZEND_REGISTER_RESOURCE(return_value, handle, le_sablot); handle->index = Z_LVAL_P(return_value); } /* }}} */ @@ -420,7 +565,7 @@ PHP_FUNCTION(xslt_run) zend_get_parameters_ex(argc, &xh, &xslt_file, &data_file, &xslt_result, &xslt_params, &xslt_args) == FAILURE) { WRONG_PARAM_COUNT; } - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron handle", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron handle", le_sablot); multi_convert_to_string_ex(2, xslt_file, data_file); if (argc == 3) { @@ -500,7 +645,7 @@ PHP_FUNCTION(xslt_openlog) zend_get_parameters_ex(argc, &xh, &logfile, &opt_loglevel) == FAILURE) { WRONG_PARAM_COUNT; } - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron", le_sablot); convert_to_string_ex(logfile); if (argc > 2) { @@ -533,7 +678,7 @@ PHP_FUNCTION(xslt_closelog) zend_get_parameters_ex(1, &xh) == FAILURE) { WRONG_PARAM_COUNT; } - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron", le_sablot); ret = SablotSetLog(handle->p, (const char *)NULL, 1); @@ -561,7 +706,7 @@ PHP_FUNCTION(xslt_fetch_result) zend_get_parameters_ex(argc, &xh, &result_name) == FAILURE) { WRONG_PARAM_COUNT; } - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", le_sablot); if (argc > 1) { convert_to_string_ex(result_name); @@ -603,7 +748,7 @@ PHP_FUNCTION(xslt_free) WRONG_PARAM_COUNT; } - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", le_sablot); zend_list_delete(Z_LVAL_PP(xh)); } /* }}} */ @@ -626,7 +771,7 @@ PHP_FUNCTION(xslt_set_sax_handler) zend_get_parameters_ex(2, &xh, &handlers) == FAILURE) { WRONG_PARAM_COUNT; } - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", le_sablot); handlers_list = HASH_OF(*handlers); @@ -692,7 +837,7 @@ PHP_FUNCTION(xslt_error) } if (argc) { - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", le_sablot); if (handle->errors) { if (array_init(return_value) == FAILURE) { @@ -735,7 +880,7 @@ PHP_FUNCTION(xslt_errno) } if (argc) { - ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", SABLOTG(le_sablot)); + ZEND_FETCH_RESOURCE(handle, php_sablot *, xh, -1, "PHP-Sablotron Handle", le_sablot); RETURN_LONG(handle->last_errno); } else { RETURN_LONG(SABLOTG(last_errno)); @@ -743,13 +888,40 @@ PHP_FUNCTION(xslt_errno) } /* }}} */ +/* {{{ proto void xslt_set_error_handler([int xh, ] string error_handler_name) + Set a error handler (either per handle or global) */ +PHP_FUNCTION(xslt_set_error_handler) +{ + zval **arg1, **arg2; + php_sablot *handle; + int argc = ZEND_NUM_ARGS(); + + if (argc > 2 || argc < 1 || + zend_get_parameters_ex(argc, &arg1, &arg2) == FAILURE) { + WRONG_PARAM_COUNT; + } + + if (argc > 1) { + convert_to_string_ex(arg2); + ZEND_FETCH_RESOURCE(handle, php_sablot *, arg1, -1, "PHP-Sablotron Handle", le_sablot); + + if (!handle->errorHandler) + MAKE_STD_ZVAL(handle->errorHandler); + + *handle->errorHandler = **arg2; + zval_copy_ctor(handle->errorHandler); + } else { + convert_to_string_ex(arg1); + + if (!SABLOTG(errorHandler)) + MAKE_STD_ZVAL(SABLOTG(errorHandler)); + + *SABLOTG(errorHandler) = **arg1; + zval_copy_ctor(SABLOTG(errorHandler)); + } +} /* }}} */ -/* }}} */ - -/* {{{ BEGIN HANDLER FUNCTIONS */ - -/* {{{ Begin SAX Handler functions */ /* {{{ _php_sablot_handler_pair() Set the handler functions from a two item array */ @@ -990,68 +1162,160 @@ static MH_ERROR _php_sablot_make_code(void *userData, SablotHandle p, int severi Handle Sablotron errors */ static MH_ERROR _php_sablot_error(void *userData, SablotHandle p, MH_ERROR code, MH_LEVEL level, char **fields) { - php_sablot *handle = (php_sablot *)userData; - - char *sep; - - int idx, - len; - - if (!fields) { - if (code) { - handle->last_errno = (int)code; - } - return(0); - } - - if (handle->errors) { - handle->errors = handle->errors_start.next; - while (handle->errors) { - S_FREE(handle->errors->key); - S_FREE(handle->errors->value); - handle->errors = handle->errors->next; - } - S_FREE(handle->errors); - } - - handle->errors_start.next = NULL; - handle->errors = &(handle->errors_start); - - while (fields && *fields) { - handle->errors->next = (php_sablot_error *)emalloc(sizeof(php_sablot_error)); - handle->errors = handle->errors->next; - - sep = strchr(fields[0], ':'); - - idx = sep - fields[0]; - len = strlen(fields[0]); - - handle->errors->key = emalloc(idx+1); - handle->errors->value = emalloc((len - idx) + 1); - memcpy(handle->errors->key, fields[0], idx); - memcpy(handle->errors->value, fields[0] + idx + 1, len - idx - 1); - - handle->errors->next = NULL; - fields++; - } - handle->last_errno = (int)code; - - switch (code) { - case MH_LEVEL_CRITICAL: - SEND_ERROR_INFO("Fatal Error", E_CORE); - return (0); - case MH_LEVEL_ERROR: - SEND_ERROR_INFO("Serious Error", E_ERROR); - return (0); - case MH_LEVEL_WARN: - SEND_ERROR_INFO("Warning", E_WARNING); - break; - } + zval **argv = NULL, + *errorHandler; + + php_sablot_error *errors, + errors_start; + php_sablot *handle = NULL; + + char *sep = NULL; + + int isAdvanced = 0, + argc = 0, + idx, + len; + + if (userData == NULL) { + SABLOT_FREE_ERROR_HANDLE(SABLOTG_HANDLE); + + SABLOTG(errors_start).next = NULL; + SABLOTG(errors) = &SABLOTG(errors_start); + + errors = SABLOTG(errors); + errorHandler = SABLOTG(errorHandler); + } else { + handle = (php_sablot *)userData; + + SABLOT_FREE_ERROR_HANDLE(*handle); + + handle->errors_start.next = NULL; + handle->errors = &errors_start; + + errors = handle->errors; + errorHandler = handle->errorHandler; + + isAdvanced = 1; + } + + + while (fields && *fields) { + errors->next = (php_sablot_error *)emalloc(sizeof(php_sablot_error)); + errors = errors->next; + + sep = strchr(fields[0], ':'); + + idx = sep - fields[0]; + len = strlen(fields[0]); + + errors->key = emalloc(idx+1); + errors->value = emalloc((len - idx) + 1); + + memcpy(errors->key, fields[0], idx); + memcpy(errors->value, fields[0] + idx + 1, len - idx - 1); + errors->value[len - idx - 1] = '\0'; + + errors->next = NULL; + fields++; + } + + if (isAdvanced) + handle->last_errno = (int)code; + else + SABLOTG(last_errno) = (int)code; + + if (errorHandler) { + zval *retval; + int i; + ELS_FETCH(); + + MAKE_STD_ZVAL(retval); + + argc = isAdvanced ? 4 : 3; + argv = emalloc(argc * sizeof(zval *)); + + MAKE_STD_ZVAL(argv[0]); + MAKE_STD_ZVAL(argv[1]); + MAKE_STD_ZVAL(argv[2]); + + if (isAdvanced) { + MAKE_STD_ZVAL(argv[3]); + + ZVAL_RESOURCE(argv[0], handle->index); + ZVAL_LONG(argv[1], code); + ZVAL_LONG(argv[2], level); + + array_init(argv[3]); + errors = handle->errors_start.next; + while (errors->next) { + add_assoc_string(argv[3], errors->key, errors->value, 1); + errors = errors->next; + } + } else { + ZVAL_LONG(argv[0], code); + ZVAL_LONG(argv[1], level); + + array_init(argv[2]); + errors = SABLOTG(errors_start).next; + while (errors) { + add_assoc_string(argv[2], errors->key, errors->value, 1); + errors = errors->next; + } + } + + if (call_user_function(EG(function_table), NULL, errorHandler, retval, argc, argv) == FAILURE) { + php_error(E_WARNING, "Sorry, couldn't call %s error handler", Z_STRVAL_P(errorHandler)); + } + + zval_dtor(retval); + efree(retval); + } else { + _php_sablot_standard_error(errors, isAdvanced ? handle->errors_start : SABLOTG(errors_start), code, level); + } return(0); + } /* }}} */ +static void _php_sablot_standard_error(php_sablot_error *errors, php_sablot_error errors_start, int code, int level) +{ + int len = 0, + pos = 0; + char *errstr = NULL; + SABLOTLS_FETCH(); + + errors = errors_start.next; + + while (errors) { + len = pos + strlen(errors->key) + sizeof(": ") + strlen(errors->value) + sizeof("\n"); + + /** + * Could be a problem, I just hate looping through strings + * more than I have to ;-) + */ + if (pos) + errstr = erealloc(errstr, len); + else + errstr = emalloc(len+1); + + sprintf(errstr + pos, "%s: %s\n", errors->key, errors->value); + + pos = len; + errors = errors->next; + } + + switch (level) { + case MH_LEVEL_CRITICAL: + case MH_LEVEL_ERROR: + php_error(E_ERROR, errstr); + break; + case MH_LEVEL_WARN: + php_error(E_WARNING, errstr); + break; + } +} + /* }}} */ /* {{{ List Handling functions */ @@ -1077,16 +1341,7 @@ static void _php_sablot_free_processor(zend_rsrc_list_entry *rsrc) FUNCH_FREE(handle->charactersHandler); FUNCH_FREE(handle->endDocHandler); - if (handle->errors) { - handle->errors = handle->errors_start.next; - while (handle->errors) { - S_FREE(handle->errors->key); - S_FREE(handle->errors->value); - handle->errors = handle->errors->next; - } - S_FREE(handle->errors); - } - S_FREE(handle); + SABLOT_FREE_ERROR_HANDLE(*handle); } /* }}} */ -- 2.40.0