Add better handling of corrupt XML data files. Print better error

messages for unknown tags, or mismatched start/end tags.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7717 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
David Hampton 2002-12-24 02:27:10 +00:00
parent 5693b12b80
commit cf6a6869e4
5 changed files with 103 additions and 81 deletions

View File

@ -1,3 +1,44 @@
2002-12-23 David Hampton <hampton@employees.org>
* src/app-file/gnc-file.c: Add missing error message.
* src/backend/file/sixtp-dom-parsers.c:
* src/backend/file/sixtp-stack.c:
* src/backend/file/sixtp.c: Better handling of corrupt XML data
files. Print better error messages for unknown tags, or
mismatched start/end tags.
* src/engine/engine-utilities.scm: Check for errors when trying to
open a new session file.
* src/engine/gw-engine-spec.scm: Added wrappers to access the
engine suspend/resume events functions.
* src/scm/command-line.scm: Suspend engine events when running
with the --add-price-quotes flag.
* src/scm/price-quotes.scm: Add some additional checking.
* src/gnome-utils/dialog-transfer.c: Change logic to multiply by
the exchange rate instead of divide. Look for both both forward
and reverse currency quotes in the pricedb. Attempt to install
currency quotes into the pricedb in a consistent manner. Give the
user better feedback on exactly what the exchange rate
means. Obsolete the currency "swap" routine. #101450
* src/gnome-utils/transfer.glade: Give the user better feedback on
exactly what the exchange rate means.
* src/register/ledger-core/split-register-control.c: Remove
function call to obolete routine.
* src/engine/gnc-pricedb.c:
* src/engine/gw-engine-spec.scm: Added a new function
(gnc_pricedb_lookup_day) to retrieve a price quote from a certain
day, not just an exact time.
2002-12-22 Chris Lyttle <chris@wilddev.net>
* rpm/gnucash.spec.in: require g-wrap 1.3.4

View File

@ -819,7 +819,7 @@ dom_tree_generic_parse(xmlNodePtr node, struct dom_tree_handler *handlers,
{
PERR("gnc_xml_set_data failed");
successful = FALSE;
break;
continue;
}
}

View File

@ -164,7 +164,7 @@ sixtp_context_run_end_handler(sixtp_parser_context* ctxt)
{
if(ctxt->top_frame->parser->end_handler)
{
ctxt->data.parsing_ok =
ctxt->data.parsing_ok &=
ctxt->top_frame->parser->end_handler(
ctxt->top_frame->data_for_children,
ctxt->top_frame->data_from_children,

View File

@ -30,6 +30,7 @@
#include <sys/types.h>
#include "sixtp.h"
#include "sixtp-parsers.h"
#include "sixtp-stack.h"
#include "gnc-engine-util.h"
@ -383,13 +384,6 @@ sixtp_sax_start_handler(void *user_data,
gboolean lookup_success = FALSE;
sixtp_stack_frame *new_frame = NULL;
/* don't replace with g_return_if_fail because we don't want to see
the critical warnings. We error elsewhere. */
if(!pdata->parsing_ok)
{
return;
}
current_frame = (sixtp_stack_frame *) pdata->stack->data;
current_parser = current_frame->parser;
@ -408,10 +402,10 @@ sixtp_sax_start_handler(void *user_data,
(gpointer) &next_parser_tag, (gpointer) &next_parser);
if(!lookup_success)
{
PERR("Tag <%s> not allowed in current context.\n",
PERR("Tag <%s> not allowed in current context.",
name ? (char *) name : "(null)");
pdata->parsing_ok = FALSE;
return;
next_parser = pdata->bad_xml_parser;
}
}
@ -429,7 +423,7 @@ sixtp_sax_start_handler(void *user_data,
parent_data_from_children = parent_frame->data_for_children;
}
pdata->parsing_ok =
pdata->parsing_ok &=
current_frame->parser->before_child(current_frame->data_for_children,
current_frame->data_from_children,
parent_data_from_children,
@ -440,8 +434,6 @@ sixtp_sax_start_handler(void *user_data,
name);
}
g_return_if_fail(pdata->parsing_ok);
/* now allocate the new stack frame and shift to it */
new_frame = sixtp_stack_frame_new(next_parser, g_strdup(name));
@ -452,7 +444,7 @@ sixtp_sax_start_handler(void *user_data,
if(next_parser->start_handler)
{
pdata->parsing_ok =
pdata->parsing_ok &=
next_parser->start_handler(current_frame->data_from_children,
current_frame->data_for_children,
pdata->global_data,
@ -469,19 +461,12 @@ sixtp_sax_characters_handler(void *user_data, const xmlChar *text, int len)
sixtp_sax_data *pdata = (sixtp_sax_data *) user_data;
sixtp_stack_frame *frame;
/* don't replace with g_return_if_fail because we don't want to see
the critical warnings. We error elsewhere. */
if(!pdata->parsing_ok)
{
return;
}
frame = (sixtp_stack_frame *) pdata->stack->data;
if(frame->parser->characters_handler)
{
gpointer result = NULL;
pdata->parsing_ok =
pdata->parsing_ok &=
frame->parser->characters_handler(frame->data_from_children,
frame->data_for_children,
pdata->global_data,
@ -514,13 +499,6 @@ sixtp_sax_end_handler(void *user_data, const xmlChar *name)
sixtp_child_result *child_result_data = NULL;
gchar *end_tag = NULL;
/* don't replace with g_return_if_fail because we don't want to see
the critical warnings. We error elsewhere. */
if(!pdata->parsing_ok)
{
return;
}
current_frame = (sixtp_stack_frame *) pdata->stack->data;
parent_frame = (sixtp_stack_frame *) pdata->stack->next->data;
@ -528,15 +506,22 @@ sixtp_sax_end_handler(void *user_data, const xmlChar *name)
necessary? */
if(safe_strcmp(current_frame->tag, name) != 0)
{
PWARN ("bad closing tag");
PWARN ("bad closing tag (start <%s>, end <%s>)", current_frame->tag, name);
pdata->parsing_ok = FALSE;
return;
/* See if we're just off by one and try to recover */
if(safe_strcmp(parent_frame->tag, name) == 0) {
pdata->stack = sixtp_pop_and_destroy_frame(pdata->stack);
current_frame = (sixtp_stack_frame *) pdata->stack->data;
parent_frame = (sixtp_stack_frame *) pdata->stack->next->data;
PWARN ("found matching start <%s> tag up one level", name);
}
}
/* tag's OK, proceed. */
if(current_frame->parser->end_handler)
{
pdata->parsing_ok =
pdata->parsing_ok &=
current_frame->parser->end_handler(current_frame->data_for_children,
current_frame->data_from_children,
parent_frame->data_from_children,
@ -546,8 +531,6 @@ sixtp_sax_end_handler(void *user_data, const xmlChar *name)
current_frame->tag);
}
g_return_if_fail(pdata->parsing_ok);
if(current_frame->frame_data)
{
/* push the result onto the parent's child result list. */
@ -595,7 +578,7 @@ sixtp_sax_end_handler(void *user_data, const xmlChar *name)
parent_data_from_children = parent_frame->data_for_children;
}
pdata->parsing_ok =
pdata->parsing_ok &=
current_frame->parser->after_child(current_frame->data_for_children,
current_frame->data_from_children,
parent_data_from_children,
@ -688,52 +671,21 @@ sixtp_handle_catastrophe(sixtp_sax_data *sax_data)
}
}
gboolean
sixtp_parse_file(sixtp *sixtp,
const char *filename,
gpointer data_for_top_level,
gpointer global_data,
gpointer *parse_result)
static gboolean
gnc_bad_xml_end_handler(gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer *result, const gchar *tag)
{
sixtp_parser_context *ctxt;
if(!(ctxt = sixtp_context_new(sixtp, global_data, data_for_top_level)))
{
PERR("sixtp_context_new returned null");
return FALSE;
}
ctxt->data.saxParserCtxt = xmlCreateFileParserCtxt( filename );
ctxt->data.saxParserCtxt->sax = &ctxt->handler;
ctxt->data.saxParserCtxt->userData = &ctxt->data;
xmlParseDocument( ctxt->data.saxParserCtxt );
//xmlSAXUserParseFile(&ctxt->handler, &ctxt->data, filename);
if(ctxt->data.parsing_ok)
{
sixtp_context_run_end_handler(ctxt);
if(parse_result)
*parse_result = ctxt->top_frame->frame_data;
sixtp_context_destroy(ctxt);
return TRUE;
}
else
{
if(parse_result)
*parse_result = NULL;
sixtp_handle_catastrophe(&ctxt->data);
sixtp_context_destroy(ctxt);
return FALSE;
}
return TRUE;
}
gboolean
sixtp_parse_buffer(sixtp *sixtp,
char *bufp,
int bufsz,
gpointer data_for_top_level,
gpointer global_data,
gpointer *parse_result)
static gboolean
sixtp_parse_file_common(sixtp *sixtp,
xmlParserCtxtPtr xml_context,
gpointer data_for_top_level,
gpointer global_data,
gpointer *parse_result)
{
sixtp_parser_context *ctxt;
@ -743,10 +695,12 @@ sixtp_parse_buffer(sixtp *sixtp,
return FALSE;
}
ctxt->data.saxParserCtxt = xmlCreateMemoryParserCtxt( bufp, bufsz );
ctxt->data.saxParserCtxt = xml_context;
ctxt->data.saxParserCtxt->sax = &ctxt->handler;
ctxt->data.saxParserCtxt->userData = &ctxt->data;
ctxt->data.bad_xml_parser = sixtp_dom_parser_new(gnc_bad_xml_end_handler, NULL, NULL);
xmlParseDocument( ctxt->data.saxParserCtxt );
//xmlSAXUserParseFile(&ctxt->handler, &ctxt->data, filename);
sixtp_context_run_end_handler(ctxt);
@ -761,12 +715,38 @@ sixtp_parse_buffer(sixtp *sixtp,
{
if(parse_result)
*parse_result = NULL;
sixtp_handle_catastrophe(&ctxt->data);
if (g_slist_length(ctxt->data.stack) > 1)
sixtp_handle_catastrophe(&ctxt->data);
sixtp_context_destroy(ctxt);
return FALSE;
}
}
gboolean
sixtp_parse_file(sixtp *sixtp,
const char *filename,
gpointer data_for_top_level,
gpointer global_data,
gpointer *parse_result)
{
xmlParserCtxtPtr context = xmlCreateFileParserCtxt( filename );
return sixtp_parse_file_common(sixtp, context, data_for_top_level,
global_data, parse_result);
}
gboolean
sixtp_parse_buffer(sixtp *sixtp,
char *bufp,
int bufsz,
gpointer data_for_top_level,
gpointer global_data,
gpointer *parse_result)
{
xmlParserCtxtPtr context = xmlCreateMemoryParserCtxt( bufp, bufsz );
return sixtp_parse_file_common(sixtp, context, data_for_top_level,
global_data, parse_result);
}
/***********************************************************************/
static gboolean
eat_whitespace(char **cursor)

View File

@ -151,6 +151,7 @@ typedef struct sixtp_sax_data {
GSList *stack;
gpointer global_data;
xmlParserCtxtPtr saxParserCtxt;
sixtp *bad_xml_parser;
} sixtp_sax_data;