mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
5693b12b80
commit
cf6a6869e4
41
ChangeLog
41
ChangeLog
@ -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>
|
2002-12-22 Chris Lyttle <chris@wilddev.net>
|
||||||
|
|
||||||
* rpm/gnucash.spec.in: require g-wrap 1.3.4
|
* rpm/gnucash.spec.in: require g-wrap 1.3.4
|
||||||
|
@ -819,7 +819,7 @@ dom_tree_generic_parse(xmlNodePtr node, struct dom_tree_handler *handlers,
|
|||||||
{
|
{
|
||||||
PERR("gnc_xml_set_data failed");
|
PERR("gnc_xml_set_data failed");
|
||||||
successful = FALSE;
|
successful = FALSE;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ sixtp_context_run_end_handler(sixtp_parser_context* ctxt)
|
|||||||
{
|
{
|
||||||
if(ctxt->top_frame->parser->end_handler)
|
if(ctxt->top_frame->parser->end_handler)
|
||||||
{
|
{
|
||||||
ctxt->data.parsing_ok =
|
ctxt->data.parsing_ok &=
|
||||||
ctxt->top_frame->parser->end_handler(
|
ctxt->top_frame->parser->end_handler(
|
||||||
ctxt->top_frame->data_for_children,
|
ctxt->top_frame->data_for_children,
|
||||||
ctxt->top_frame->data_from_children,
|
ctxt->top_frame->data_from_children,
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "sixtp.h"
|
#include "sixtp.h"
|
||||||
|
#include "sixtp-parsers.h"
|
||||||
#include "sixtp-stack.h"
|
#include "sixtp-stack.h"
|
||||||
|
|
||||||
#include "gnc-engine-util.h"
|
#include "gnc-engine-util.h"
|
||||||
@ -383,13 +384,6 @@ sixtp_sax_start_handler(void *user_data,
|
|||||||
gboolean lookup_success = FALSE;
|
gboolean lookup_success = FALSE;
|
||||||
sixtp_stack_frame *new_frame = NULL;
|
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_frame = (sixtp_stack_frame *) pdata->stack->data;
|
||||||
current_parser = current_frame->parser;
|
current_parser = current_frame->parser;
|
||||||
|
|
||||||
@ -408,10 +402,10 @@ sixtp_sax_start_handler(void *user_data,
|
|||||||
(gpointer) &next_parser_tag, (gpointer) &next_parser);
|
(gpointer) &next_parser_tag, (gpointer) &next_parser);
|
||||||
if(!lookup_success)
|
if(!lookup_success)
|
||||||
{
|
{
|
||||||
PERR("Tag <%s> not allowed in current context.\n",
|
PERR("Tag <%s> not allowed in current context.",
|
||||||
name ? (char *) name : "(null)");
|
name ? (char *) name : "(null)");
|
||||||
pdata->parsing_ok = FALSE;
|
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;
|
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->parser->before_child(current_frame->data_for_children,
|
||||||
current_frame->data_from_children,
|
current_frame->data_from_children,
|
||||||
parent_data_from_children,
|
parent_data_from_children,
|
||||||
@ -440,8 +434,6 @@ sixtp_sax_start_handler(void *user_data,
|
|||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_if_fail(pdata->parsing_ok);
|
|
||||||
|
|
||||||
/* now allocate the new stack frame and shift to it */
|
/* now allocate the new stack frame and shift to it */
|
||||||
new_frame = sixtp_stack_frame_new(next_parser, g_strdup(name));
|
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)
|
if(next_parser->start_handler)
|
||||||
{
|
{
|
||||||
pdata->parsing_ok =
|
pdata->parsing_ok &=
|
||||||
next_parser->start_handler(current_frame->data_from_children,
|
next_parser->start_handler(current_frame->data_from_children,
|
||||||
current_frame->data_for_children,
|
current_frame->data_for_children,
|
||||||
pdata->global_data,
|
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_sax_data *pdata = (sixtp_sax_data *) user_data;
|
||||||
sixtp_stack_frame *frame;
|
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;
|
frame = (sixtp_stack_frame *) pdata->stack->data;
|
||||||
if(frame->parser->characters_handler)
|
if(frame->parser->characters_handler)
|
||||||
{
|
{
|
||||||
gpointer result = NULL;
|
gpointer result = NULL;
|
||||||
|
|
||||||
pdata->parsing_ok =
|
pdata->parsing_ok &=
|
||||||
frame->parser->characters_handler(frame->data_from_children,
|
frame->parser->characters_handler(frame->data_from_children,
|
||||||
frame->data_for_children,
|
frame->data_for_children,
|
||||||
pdata->global_data,
|
pdata->global_data,
|
||||||
@ -514,13 +499,6 @@ sixtp_sax_end_handler(void *user_data, const xmlChar *name)
|
|||||||
sixtp_child_result *child_result_data = NULL;
|
sixtp_child_result *child_result_data = NULL;
|
||||||
gchar *end_tag = 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;
|
current_frame = (sixtp_stack_frame *) pdata->stack->data;
|
||||||
parent_frame = (sixtp_stack_frame *) pdata->stack->next->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? */
|
necessary? */
|
||||||
if(safe_strcmp(current_frame->tag, name) != 0)
|
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;
|
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. */
|
/* tag's OK, proceed. */
|
||||||
if(current_frame->parser->end_handler)
|
if(current_frame->parser->end_handler)
|
||||||
{
|
{
|
||||||
pdata->parsing_ok =
|
pdata->parsing_ok &=
|
||||||
current_frame->parser->end_handler(current_frame->data_for_children,
|
current_frame->parser->end_handler(current_frame->data_for_children,
|
||||||
current_frame->data_from_children,
|
current_frame->data_from_children,
|
||||||
parent_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);
|
current_frame->tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_if_fail(pdata->parsing_ok);
|
|
||||||
|
|
||||||
if(current_frame->frame_data)
|
if(current_frame->frame_data)
|
||||||
{
|
{
|
||||||
/* push the result onto the parent's child result list. */
|
/* 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;
|
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->parser->after_child(current_frame->data_for_children,
|
||||||
current_frame->data_from_children,
|
current_frame->data_from_children,
|
||||||
parent_data_from_children,
|
parent_data_from_children,
|
||||||
@ -688,52 +671,21 @@ sixtp_handle_catastrophe(sixtp_sax_data *sax_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static gboolean
|
||||||
sixtp_parse_file(sixtp *sixtp,
|
gnc_bad_xml_end_handler(gpointer data_for_children,
|
||||||
const char *filename,
|
GSList* data_from_children, GSList* sibling_data,
|
||||||
gpointer data_for_top_level,
|
gpointer parent_data, gpointer global_data,
|
||||||
gpointer global_data,
|
gpointer *result, const gchar *tag)
|
||||||
gpointer *parse_result)
|
|
||||||
{
|
{
|
||||||
sixtp_parser_context *ctxt;
|
return TRUE;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
static gboolean
|
||||||
sixtp_parse_buffer(sixtp *sixtp,
|
sixtp_parse_file_common(sixtp *sixtp,
|
||||||
char *bufp,
|
xmlParserCtxtPtr xml_context,
|
||||||
int bufsz,
|
gpointer data_for_top_level,
|
||||||
gpointer data_for_top_level,
|
gpointer global_data,
|
||||||
gpointer global_data,
|
gpointer *parse_result)
|
||||||
gpointer *parse_result)
|
|
||||||
{
|
{
|
||||||
sixtp_parser_context *ctxt;
|
sixtp_parser_context *ctxt;
|
||||||
|
|
||||||
@ -743,10 +695,12 @@ sixtp_parse_buffer(sixtp *sixtp,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt->data.saxParserCtxt = xmlCreateMemoryParserCtxt( bufp, bufsz );
|
ctxt->data.saxParserCtxt = xml_context;
|
||||||
ctxt->data.saxParserCtxt->sax = &ctxt->handler;
|
ctxt->data.saxParserCtxt->sax = &ctxt->handler;
|
||||||
ctxt->data.saxParserCtxt->userData = &ctxt->data;
|
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 );
|
xmlParseDocument( ctxt->data.saxParserCtxt );
|
||||||
|
//xmlSAXUserParseFile(&ctxt->handler, &ctxt->data, filename);
|
||||||
|
|
||||||
sixtp_context_run_end_handler(ctxt);
|
sixtp_context_run_end_handler(ctxt);
|
||||||
|
|
||||||
@ -761,12 +715,38 @@ sixtp_parse_buffer(sixtp *sixtp,
|
|||||||
{
|
{
|
||||||
if(parse_result)
|
if(parse_result)
|
||||||
*parse_result = NULL;
|
*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);
|
sixtp_context_destroy(ctxt);
|
||||||
return FALSE;
|
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
|
static gboolean
|
||||||
eat_whitespace(char **cursor)
|
eat_whitespace(char **cursor)
|
||||||
|
@ -151,6 +151,7 @@ typedef struct sixtp_sax_data {
|
|||||||
GSList *stack;
|
GSList *stack;
|
||||||
gpointer global_data;
|
gpointer global_data;
|
||||||
xmlParserCtxtPtr saxParserCtxt;
|
xmlParserCtxtPtr saxParserCtxt;
|
||||||
|
sixtp *bad_xml_parser;
|
||||||
} sixtp_sax_data;
|
} sixtp_sax_data;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user