From c3b8cdcfc6a40c7a518850974cef7455d0b6c9e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=C3=B6hler?= Date: Sun, 28 May 2006 17:47:12 +0000 Subject: [PATCH] Move is_gzipped_file to io-gncxml-v2.c. Extend try_gz_open to read from gzipped files. Let gnc_xml2_find_ambiguous and parse_with_subst_push_handler read gzipped files. Add gnc_is_our_first_xml_chunk. Remove "error" from argument list of gnc_xml2_find_ambiguous. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@14217 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 15 ++ src/backend/file/gnc-backend-file.c | 27 ---- src/backend/file/io-gncxml-v2.c | 190 ++++++++++++++++--------- src/backend/file/io-gncxml-v2.h | 4 +- src/backend/file/sixtp.c | 34 +++-- src/backend/file/sixtp.h | 3 + src/gnome-utils/druid-gnc-xml-import.c | 5 +- 7 files changed, 161 insertions(+), 117 deletions(-) diff --git a/ChangeLog b/ChangeLog index 68770be76c..278111fb53 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-05-28 Andreas Köhler + + * src/backend/file/gnc-backend-file.c: + * src/backend/file/io-gncxml-v2.c: Move is_gzipped_file to + io-gncxml-v2.c. Extend try_gz_open to read from gzipped files. + Let gnc_xml2_find_ambiguous and parse_with_subst_push_handler + read gzipped files. + + * src/backend/file/sixtp.c: + * src/backend/file/sixtp.h: Add gnc_is_our_first_xml_chunk. + + * src/backend/file/io-gncxml-v2.h: + * src/gnome-utils/druid-gnc-xml-import.c: Remove "error" from + argument list of gnc_xml2_find_ambiguous. + 2006-05-27 Joshua Sled * packaging/gnucash-1.9.x.ebuild: Add docs extraction, un-slot, diff --git a/src/backend/file/gnc-backend-file.c b/src/backend/file/gnc-backend-file.c index adfb5734a4..06876e6fca 100644 --- a/src/backend/file/gnc-backend-file.c +++ b/src/backend/file/gnc-backend-file.c @@ -391,30 +391,6 @@ gnc_int_link_or_make_backup(FileBackend *be, const char *orig, const char *bkup) /* ================================================================= */ -static gboolean -is_gzipped_file(const gchar *name) -{ - unsigned char buf[2]; - int fd = open(name, O_RDONLY); - - if(fd == 0) - { - return FALSE; - } - - if(read(fd, buf, 2) != 2) - { - return FALSE; - } - - if(buf[0] == 037 && buf[1] == 0213) - { - return TRUE; - } - - return FALSE; -} - static QofBookFileType gnc_file_be_determine_file_type(const char *path) { @@ -427,8 +403,6 @@ gnc_file_be_determine_file_type(const char *path) } } else if (gnc_is_xml_data_file(path)) { return GNC_BOOK_XML1_FILE; - } else if (is_gzipped_file(path)) { - return GNC_BOOK_XML2_FILE; } else if (gnc_is_bin_file(path)) { return GNC_BOOK_BIN_FILE; } @@ -452,7 +426,6 @@ gnc_determine_file_type (const char *path) if (sbuf.st_size == 0) { PINFO (" empty file"); return TRUE; } if(gnc_is_xml_data_file_v2(path, NULL)) { return TRUE; } else if(gnc_is_xml_data_file(path)) { return TRUE; } - else if(is_gzipped_file(path)) { return TRUE; } else if(gnc_is_bin_file(path)) { return TRUE; } PINFO (" %s is not a gnc file", path); return FALSE; diff --git a/src/backend/file/io-gncxml-v2.c b/src/backend/file/io-gncxml-v2.c index b895a2c698..d1b4d601ff 100644 --- a/src/backend/file/io-gncxml-v2.c +++ b/src/backend/file/io-gncxml-v2.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -1233,7 +1234,8 @@ gnc_book_write_accounts_to_xml_filehandle_v2(QofBackend *be, QofBook *book, FILE #define BUFLEN 4096 static FILE * -try_gz_open (const char *filename, const char *perms, gboolean use_gzip) +try_gz_open (const char *filename, const char *perms, gboolean use_gzip, + gboolean compress) { if (strstr(filename, ".gz.") != NULL) /* its got a temp extension */ use_gzip = TRUE; @@ -1249,7 +1251,8 @@ try_gz_open (const char *filename, const char *perms, gboolean use_gzip) the g_spawn glib wrappers. */ { /* Start gzip from a command line, not by fork(). */ - gchar *argv[] = {"gzip", NULL}; + gchar *argv[] = {compress ? "gzip" : "gunzip", + NULL}; GPid child_pid; GError *error; int child_stdin; @@ -1268,7 +1271,7 @@ try_gz_open (const char *filename, const char *perms, gboolean use_gzip) /* FIXME: Now need to set up the child process to write to the file. */ - return fdopen(child_stdin, "w"); + return fdopen(child_stdin, compress ? "w" : "r"); /* Eventually the GPid must be cleanup up, but not here? */ /* g_spawn_close_pid(child_pid); */ @@ -1293,24 +1296,39 @@ try_gz_open (const char *filename, const char *perms, gboolean use_gzip) case 0: /* child */ { char buffer[BUFLEN]; unsigned bytes; - gzFile *out; + gzFile *file; - close(filedes[1]); - out = gzopen(filename, perms); - if (out == NULL) { - PWARN("child gzopen failed\n"); - exit(0); + file = gzopen(filename, perms); + if (file == NULL) { + PWARN("child gzopen failed\n"); + exit(0); } - while ((bytes = read(filedes[0], buffer, BUFLEN)) > 0) - gzwrite(out, buffer, bytes); - gzclose(out); + if (compress) { + close(filedes[1]); + while ((bytes = read(filedes[0], buffer, BUFLEN)) > 0) + gzwrite(file, buffer, bytes); + } + else + { + close(filedes[0]); + while ((bytes = gzread(file, buffer, BUFLEN)) > 0) + write(filedes[1], buffer, bytes); + } + gzclose(file); _exit(0); } default: /* parent */ sleep(2); - close(filedes[0]); - return fdopen(filedes[1], "w"); + if (compress) { + close(filedes[0]); + return fdopen(filedes[1], "w"); + } + else + { + close(filedes[1]); + return fdopen(filedes[0], "r"); + } } } #endif @@ -1324,7 +1342,7 @@ gnc_book_write_to_xml_file_v2( { FILE *out; - out = try_gz_open(filename, "w", compress); + out = try_gz_open(filename, "w", compress, TRUE); if (out == NULL) { return FALSE; @@ -1374,10 +1392,55 @@ gnc_book_write_accounts_to_xml_file_v2( } /***********************************************************************/ +static gboolean +is_gzipped_file(const gchar *name) +{ + unsigned char buf[2]; + int fd = open(name, O_RDONLY); + + if (fd == -1) { + return FALSE; + } + + if (read(fd, buf, 2) != 2) { + close(fd); + return FALSE; + } + close(fd); + + if (buf[0] == 037 && buf[1] == 0213) { + return TRUE; + } + + return FALSE; +} + gboolean gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding) { - return gnc_is_our_xml_file(name, GNC_V2_STRING, with_encoding); + if (gnc_is_our_xml_file(name, GNC_V2_STRING, with_encoding)) + return TRUE; + + if (is_gzipped_file(name)) { + gzFile *file; + char first_chunk[256]; + int num_read; + + file = gzopen(name, "r"); + if (file == NULL) + return FALSE; + + num_read = gzread(file, first_chunk, sizeof(first_chunk) - 1); + gzclose(file); + + if (num_read < 1) + return FALSE; + + return gnc_is_our_first_xml_chunk(first_chunk, GNC_V2_STRING, + with_encoding); + } + + return FALSE; } @@ -1447,29 +1510,25 @@ typedef struct { gint gnc_xml2_find_ambiguous(const gchar *filename, GList *encodings, GHashTable **unique, GHashTable **ambiguous, - GList **impossible, GError **error) + GList **impossible) { - GIOChannel *channel=NULL; - GIOStatus status; + FILE *file=NULL; GList *iconv_list=NULL, *conv_list=NULL, *iter; iconv_item_type *iconv_item=NULL, *ascii=NULL; const gchar *enc; GHashTable *processed=NULL; gint n_impossible = 0; - gboolean clean_return = FALSE; + GError *error=NULL; + gboolean is_compressed; + gboolean clean_return=FALSE; - channel = g_io_channel_new_file(filename, "r", error); - if (*error) { + 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); goto cleanup_find_ambs; } - status = g_io_channel_set_encoding(channel, NULL, error); - if (status != G_IO_STATUS_NORMAL) { - PWARN("Error on unsetting encoding on IOChannel"); - goto cleanup_find_ambs; - } - /* we need ascii */ ascii = g_new(iconv_item_type, 1); ascii->encoding = g_quark_from_string("ASCII"); @@ -1510,25 +1569,21 @@ gnc_xml2_find_ambiguous(const gchar *filename, GList *encodings, /* loop through lines */ while (1) { - gchar *line, *word, *utf8; + gchar line[256], *word, *utf8; gchar **word_array, **word_cursor; conv_type *conv = NULL; - status = g_io_channel_read_line(channel, &line, NULL, NULL, error); - if (status == G_IO_STATUS_EOF) { - break; - } - if (status == G_IO_STATUS_AGAIN) { - continue; - } - if (status != G_IO_STATUS_NORMAL) { - goto cleanup_find_ambs; + if (!fgets(line, sizeof(line)-1, file)) { + if (feof(file)) { + break; + } else { + goto cleanup_find_ambs; + } } g_strchomp(line); replace_character_references(line); word_array = g_strsplit_set(line, "> <", 0); - g_free(line); /* loop through words */ for (word_cursor = word_array; *word_cursor; word_cursor++) { @@ -1537,14 +1592,14 @@ gnc_xml2_find_ambiguous(const gchar *filename, GList *encodings, continue; utf8 = g_convert_with_iconv(word, -1, ascii->iconv, - NULL, NULL, error); + NULL, NULL, &error); if (utf8) { /* pure ascii */ g_free(utf8); continue; } - g_error_free(*error); - *error = NULL; + g_error_free(error); + error = NULL; if (g_hash_table_lookup_extended(processed, word, NULL, NULL)) { /* already processed */ @@ -1556,15 +1611,15 @@ gnc_xml2_find_ambiguous(const gchar *filename, GList *encodings, for (iter = iconv_list; iter; iter = iter->next) { iconv_item = iter->data; utf8 = g_convert_with_iconv(word, -1, iconv_item->iconv, - NULL, NULL, error); + NULL, NULL, &error); if (utf8) { conv = g_new(conv_type, 1); conv->encoding = iconv_item->encoding; conv->utf8_string = utf8; conv_list = g_list_prepend(conv_list, conv); } else { - g_error_free(*error); - *error = NULL; + g_error_free(error); + error = NULL; } } @@ -1616,8 +1671,8 @@ gnc_xml2_find_ambiguous(const gchar *filename, GList *encodings, g_hash_table_destroy(processed); if (ascii) g_free(ascii); - if (channel) - g_io_channel_unref(channel); + if (file) + fclose(file); return (clean_return) ? n_impossible : -1; } @@ -1631,21 +1686,18 @@ static void parse_with_subst_push_handler (xmlParserCtxtPtr xml_context, push_data_type *push_data) { - GIOChannel *channel=NULL; - GIOStatus status; + const gchar *filename; + FILE *file = NULL; GIConv ascii=(GIConv)-1; GString *output=NULL; GError *error=NULL; + gboolean is_compressed; - channel = g_io_channel_new_file(push_data->filename, "r", &error); - if (error) { - PWARN("Unable to open file %s", push_data->filename); - goto cleanup_push_handler; - } - - status = g_io_channel_set_encoding(channel, NULL, &error); - if (status != G_IO_STATUS_NORMAL) { - PWARN("Error on unsetting encoding on IOChannel"); + filename = push_data->filename; + 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); goto cleanup_push_handler; } @@ -1657,24 +1709,20 @@ parse_with_subst_push_handler (xmlParserCtxtPtr xml_context, /* loop through lines */ while (1) { - gchar *line, *word, *repl, *utf8; + gchar line[256], *word, *repl, *utf8; gint pos, len; gchar *start, *cursor; - status = g_io_channel_read_line(channel, &line, NULL, NULL, &error); - if (status == G_IO_STATUS_EOF) { - break; - } - if (status == G_IO_STATUS_AGAIN) { - continue; - } - if (status != G_IO_STATUS_NORMAL) { - goto cleanup_push_handler; + if (!fgets(line, sizeof(line)-1, file)) { + if (feof(file)) { + break; + } else { + goto cleanup_push_handler; + } } replace_character_references(line); output = g_string_new(line); - g_free(line); /* loop through words */ cursor = output->str; @@ -1740,8 +1788,8 @@ parse_with_subst_push_handler (xmlParserCtxtPtr xml_context, g_string_free(output, TRUE); if (ascii != (GIConv) -1) g_iconv_close(ascii); - if (channel) - g_io_channel_unref(channel); + if (file) + fclose(file); } gboolean diff --git a/src/backend/file/io-gncxml-v2.h b/src/backend/file/io-gncxml-v2.h index 4bec8d693b..6d76ae04ba 100644 --- a/src/backend/file/io-gncxml-v2.h +++ b/src/backend/file/io-gncxml-v2.h @@ -180,10 +180,10 @@ typedef struct { */ gint gnc_xml2_find_ambiguous( const gchar *filename, GList *encodings, GHashTable **unique, - GHashTable **ambiguous, GList **impossible, GError **error); + GHashTable **ambiguous, GList **impossible); typedef gint (*find_ambiguous_handler)( const gchar *filename, GList *encodings, GHashTable **unique, - GHashTable **ambiguous, GList **impossible, GError **error); + GHashTable **ambiguous, GList **impossible); /** Parse a file in push mode, but replace byte sequences in the file given a * hash table of substitutions diff --git a/src/backend/file/sixtp.c b/src/backend/file/sixtp.c index 0e55609d41..d22e96bffe 100644 --- a/src/backend/file/sixtp.c +++ b/src/backend/file/sixtp.c @@ -838,16 +838,11 @@ gnc_is_our_xml_file(const char *filename, const char *first_tag, { FILE *f = NULL; char first_chunk[256]; - unsigned char* cursor = NULL; ssize_t num_read; - + g_return_val_if_fail(filename, FALSE); g_return_val_if_fail(first_tag, FALSE); - if (with_encoding) { - *with_encoding = FALSE; - } - f = fopen(filename, "r"); if (f == NULL) { return FALSE; @@ -856,21 +851,34 @@ gnc_is_our_xml_file(const char *filename, const char *first_tag, num_read = fread(first_chunk, sizeof(char), sizeof(first_chunk) - 1, f); fclose(f); - if(num_read == 0) + if(num_read == 0) { return FALSE; } - + first_chunk[num_read] = '\0'; - - cursor = first_chunk; + + return gnc_is_our_first_xml_chunk(first_chunk, first_tag, with_encoding); +} + +gboolean +gnc_is_our_first_xml_chunk(char *chunk, const char *first_tag, + gboolean *with_encoding) +{ + unsigned char* cursor = NULL; + + if (with_encoding) { + *with_encoding = FALSE; + } + + cursor = chunk; if(!eat_whitespace(&cursor)) { return FALSE; } - - if(strncmp(cursor, "encodings) { gboolean is_utf8; const gchar *locale_enc; @@ -630,8 +628,7 @@ gxi_check_file (GncXmlImportData *data) /* analyze file */ data->n_impossible = (*find_ambiguous) ( - data->filename, data->encodings, &data->unique, &data->ambiguous_ht, - NULL, &error); + data->filename, data->encodings, &data->unique, &data->ambiguous_ht, NULL); if (data->n_impossible != -1) { /* sort ambiguous words */