Decompress zipped XML files ourself instead of letting libxml2 do it.

As of version 2.9.1 it has a bug that causes it to fail to decompress certain files.
See https://bugzilla.gnome.org/show_bug.cgi?id=712528 for more info.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@23412 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Mike Alexander 2013-11-19 03:47:07 +00:00
parent 77471eb70b
commit 390c14aec2
5 changed files with 91 additions and 2 deletions

View File

@ -41,3 +41,19 @@ gnc_xml_parse_file(sixtp *top_parser, const char *filename,
return sixtp_parse_file(top_parser, filename,
NULL, &gpdata, &parse_result);
}
gboolean
gnc_xml_parse_fd(sixtp *top_parser, FILE *fd,
gxpf_callback callback, gpointer parsedata,
gpointer bookdata)
{
gpointer parse_result = NULL;
gxpf_data gpdata;
gpdata.cb = callback;
gpdata.parsedata = parsedata;
gpdata.bookdata = bookdata;
return sixtp_parse_fd(top_parser, fd,
NULL, &gpdata, &parse_result);
}

View File

@ -45,4 +45,9 @@ gnc_xml_parse_file(sixtp *top_parser, const char *filename,
gxpf_callback callback, gpointer parsedata,
gpointer bookdata);
gboolean
gnc_xml_parse_fd(sixtp *top_parser, FILE *fd,
gxpf_callback callback, gpointer parsedata,
gpointer bookdata);
#endif /* IO_GNCXML_GEN_H */

View File

@ -99,6 +99,12 @@ struct file_backend
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
extern const gchar *gnc_v2_book_version_string; /* see gnc-book-xml-v2 */
/* Forward declarations */
static FILE *try_gz_open (const char *filename, const char *perms, gboolean use_gzip,
gboolean compress);
static gboolean is_gzipped_file(const gchar *name);
static gboolean wait_for_gzip(FILE *file);
void
run_callback(sixtp_gdv2 *data, const char *type)
{
@ -774,8 +780,38 @@ qof_session_load_from_xml_file_v2_full(
}
else
{
retval = gnc_xml_parse_file(top_parser, fbe->fullpath,
generic_callback, gd, book);
/* Even though libxml2 knows how to decompress zipped files, we do it
ourself since as of version 2.9.1 it has a bug that causes it to fail
to decompress certain files.
See https://bugzilla.gnome.org/show_bug.cgi?id=712528 for more info */
gchar *filename = fbe->fullpath;
#ifdef G_OS_WIN32
filename = g_win32_locale_filename_from_utf8(fbe->fulpath);
if (filename)
{
#endif
FILE *file;
gboolean is_compressed = is_gzipped_file(filename);
file = try_gz_open(filename, "r", is_compressed, FALSE);
if (file == NULL)
{
PWARN("Unable to open file %s", filename);
retval = FALSE;
}
else
{
retval = gnc_xml_parse_fd(top_parser, file,
generic_callback, gd, book);
fclose(file);
if (is_compressed)
wait_for_gzip(file);
}
#ifdef G_OS_WIN32
g_free(filename);
else
retval = FALSE;
}
#endif
}
if (!retval)

View File

@ -28,6 +28,7 @@
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef _MSC_VER
typedef int ssize_t;
@ -759,6 +760,34 @@ sixtp_parse_file(sixtp *sixtp,
return ret;
}
/* Call back function for libxml2 to read from compressed or uncompressed stream */
static int
sixtp_parser_read(void *context, char *buffer, int len)
{
int ret;
ret = fread(&buffer[0], sizeof(char), len, (FILE *) context);
if (ret < 0)
g_warning("Error reading XML file");
return ret;
}
gboolean
sixtp_parse_fd(sixtp *sixtp,
FILE *fd,
gpointer data_for_top_level,
gpointer global_data,
gpointer *parse_result)
{
gboolean ret;
xmlParserCtxtPtr context = xmlCreateIOParserCtxt( NULL, NULL,
sixtp_parser_read, NULL /*no close */, fd,
XML_CHAR_ENCODING_NONE);
ret = sixtp_parse_file_common(sixtp, context, data_for_top_level,
global_data, parse_result);
return ret;
}
gboolean
sixtp_parse_buffer(sixtp *sixtp,
char *bufp,

View File

@ -185,6 +185,9 @@ xmlEntityPtr sixtp_sax_get_entity_handler(void *user_data, const xmlChar *name);
gboolean sixtp_parse_file(sixtp *sixtp, const char *filename,
gpointer data_for_top_level, gpointer global_data,
gpointer *parse_result);
gboolean sixtp_parse_fd(sixtp *sixtp, FILE *fd,
gpointer data_for_top_level, gpointer global_data,
gpointer *parse_result);
gboolean sixtp_parse_buffer(sixtp *sixtp, char *bufp, int bufsz,
gpointer data_for_top_level, gpointer global_data,
gpointer *parse_result);