Update xml file backend to recognize a newer version file on load attempt, not load, and alert user of need to upgrade Gnucash.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@21908 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
J. Alex Aycinena 2012-01-29 01:12:30 +00:00
parent c2458bfc68
commit 7c03e237b2
19 changed files with 134 additions and 73 deletions

View File

@ -99,15 +99,6 @@ typedef int ssize_t;
static QofLogModule log_module = GNC_MOD_BACKEND;
typedef enum
{
GNC_BOOK_NOT_OURS,
GNC_BOOK_BIN_FILE,
GNC_BOOK_XML1_FILE,
GNC_BOOK_XML2_FILE,
GNC_BOOK_XML2_FILE_NO_ENCODING,
} QofBookFileType;
static gboolean save_may_clobber_data (QofBackend *bend);
/* ================================================================= */
@ -561,7 +552,10 @@ static QofBookFileType
gnc_xml_be_determine_file_type(const char *path)
{
gboolean with_encoding;
if (gnc_is_xml_data_file_v2(path, &with_encoding))
QofBookFileType v2type;
v2type = gnc_is_xml_data_file_v2(path, &with_encoding);
if (v2type == GNC_BOOK_XML2_FILE)
{
if (with_encoding)
{
@ -572,7 +566,11 @@ gnc_xml_be_determine_file_type(const char *path)
return GNC_BOOK_XML2_FILE_NO_ENCODING;
}
}
else if (gnc_is_xml_data_file(path))
else if (v2type == GNC_BOOK_POST_XML2_0_0_FILE)
{
return GNC_BOOK_POST_XML2_0_0_FILE;
}
else if (v2type == GNC_BOOK_XML1_FILE)
{
return GNC_BOOK_XML1_FILE;
}
@ -586,6 +584,7 @@ gnc_determine_file_type (const char *uri)
int rc;
FILE *t;
gchar *filename;
QofBookFileType xml_type;
gboolean result;
if (!uri)
@ -619,12 +618,10 @@ gnc_determine_file_type (const char *uri)
result = TRUE;
goto det_exit;
}
if (gnc_is_xml_data_file_v2(filename, NULL))
{
result = TRUE;
goto det_exit;
}
else if (gnc_is_xml_data_file(filename))
xml_type = gnc_is_xml_data_file_v2(filename, NULL);
if ((xml_type == GNC_BOOK_XML2_FILE) ||
(xml_type == GNC_BOOK_XML1_FILE) ||
(xml_type == GNC_BOOK_POST_XML2_0_0_FILE))
{
result = TRUE;
goto det_exit;
@ -1117,7 +1114,7 @@ gnc_xml_be_load_from_file (QofBackend *bend, QofBook *book, QofBackendLoadType l
switch (gnc_xml_be_determine_file_type(be->fullpath))
{
case GNC_BOOK_XML2_FILE:
rc = qof_session_load_from_xml_file_v2 (be, book);
rc = qof_session_load_from_xml_file_v2 (be, book, GNC_BOOK_XML2_FILE);
if (FALSE == rc)
{
PWARN( "Syntax error in Xml File %s", be->fullpath );
@ -1137,6 +1134,10 @@ gnc_xml_be_load_from_file (QofBackend *bend, QofBook *book, QofBackendLoadType l
error = ERR_FILEIO_PARSE_ERROR;
}
break;
case GNC_BOOK_POST_XML2_0_0_FILE:
error = ERR_BACKEND_TOO_NEW;
PWARN( "Version of Xml file %s is newer than what we can read", be->fullpath );
break;
default:
/* If file type wasn't known, check errno again to give the
user some more useful feedback for some particular error

View File

@ -43,6 +43,16 @@ typedef enum
XML_RETAIN_ALL
} XMLFileRetentionType;
typedef enum
{
GNC_BOOK_NOT_OURS,
GNC_BOOK_BIN_FILE,
GNC_BOOK_XML1_FILE,
GNC_BOOK_XML2_FILE,
GNC_BOOK_XML2_FILE_NO_ENCODING,
GNC_BOOK_POST_XML2_0_0_FILE
} QofBookFileType;
struct FileBackend_struct
{
QofBackend be;

View File

@ -498,8 +498,9 @@ gnc_load_example_account_list(const char *dirname)
/***********************************************************************/
/*
gboolean
gnc_is_example_account_xml(const gchar *name)
{
return gnc_is_our_xml_file(name, GNC_ACCOUNT_STRING, NULL);
}
} */

View File

@ -53,6 +53,6 @@ GncExampleAccount *gnc_read_example_account(const gchar *filename);
void gnc_free_example_account_list(GSList *list);
GSList* gnc_load_example_account_list(const char *dirname);
gboolean gnc_is_example_account_xml(const gchar *name);
/* gboolean gnc_is_example_account_xml(const gchar *name); */
#endif /* IO_EXAMPLE_ACCOUNT_H */

View File

@ -412,7 +412,9 @@ qof_session_load_from_xml_file(QofBook *book, const char *filename)
gboolean
gnc_is_xml_data_file(const gchar *filename)
{
return gnc_is_our_xml_file(filename, "gnc", NULL);
if ((gnc_is_our_xml_file(filename, NULL)) == GNC_BOOK_XML1_FILE)
return TRUE;
return FALSE;
}
/* ================================================================== */

View File

@ -95,6 +95,8 @@ struct file_backend
};
#define GNC_V2_STRING "gnc-v2"
/* non-static because they are used in sixtp.c */
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
extern const gchar *gnc_v2_book_version_string; /* see gnc-book-xml-v2 */
void
@ -679,7 +681,8 @@ gnc_sixtp_gdv2_new (
static gboolean
qof_session_load_from_xml_file_v2_full(
FileBackend *fbe, QofBook *book,
sixtp_push_handler push_handler, gpointer push_user_data)
sixtp_push_handler push_handler, gpointer push_user_data,
QofBookFileType type)
{
Account *root;
QofBackend *be = &fbe->be;
@ -689,6 +692,7 @@ qof_session_load_from_xml_file_v2_full(
sixtp *book_parser;
struct file_backend be_data;
gboolean retval;
char *v2type;
gd = gnc_sixtp_gdv2_new(book, FALSE, file_rw_feedback, be->percentage);
@ -696,14 +700,20 @@ qof_session_load_from_xml_file_v2_full(
main_parser = sixtp_new();
book_parser = sixtp_new();
if (type == GNC_BOOK_XML2_FILE)
v2type = g_strdup(GNC_V2_STRING);
if (!sixtp_add_some_sub_parsers(
top_parser, TRUE,
GNC_V2_STRING, main_parser,
v2type, main_parser,
NULL, NULL))
{
g_free(v2type);
goto bail;
}
g_free(v2type);
if (!sixtp_add_some_sub_parsers(
main_parser, TRUE,
COUNT_DATA_TAG, gnc_counter_sixtp_parser_create(),
@ -819,9 +829,10 @@ bail:
}
gboolean
qof_session_load_from_xml_file_v2(FileBackend *fbe, QofBook *book)
qof_session_load_from_xml_file_v2(FileBackend *fbe, QofBook *book,
QofBookFileType type)
{
return qof_session_load_from_xml_file_v2_full(fbe, book, NULL, NULL);
return qof_session_load_from_xml_file_v2_full(fbe, book, NULL, NULL, type);
}
/***********************************************************************/
@ -1620,12 +1631,9 @@ is_gzipped_file(const gchar *name)
return FALSE;
}
gboolean
QofBookFileType
gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding)
{
if (gnc_is_our_xml_file(name, GNC_V2_STRING, with_encoding))
return TRUE;
if (is_gzipped_file(name))
{
gzFile *file = NULL;
@ -1647,19 +1655,18 @@ gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding)
file = gzopen(name, "r");
#endif
if (file == NULL)
return FALSE;
return GNC_BOOK_NOT_OURS;
num_read = gzread(file, first_chunk, sizeof(first_chunk) - 1);
gzclose(file);
if (num_read < 1)
return FALSE;
return GNC_BOOK_NOT_OURS;
return gnc_is_our_first_xml_chunk(first_chunk, GNC_V2_STRING,
with_encoding);
return gnc_is_our_first_xml_chunk(first_chunk, with_encoding);
}
return FALSE;
return (gnc_is_our_xml_file(name, with_encoding));
}
@ -2095,7 +2102,7 @@ gnc_xml2_parse_with_subst (FileBackend *fbe, QofBook *book, GHashTable *subst)
success = qof_session_load_from_xml_file_v2_full(
fbe, book, (sixtp_push_handler) parse_with_subst_push_handler,
push_data);
push_data, GNC_BOOK_XML2_FILE);
if (success)
qof_book_kvp_changed(book);

View File

@ -128,7 +128,7 @@ typedef struct
void run_callback(sixtp_gdv2 *data, const char *type);
/** read in an account group from a file */
gboolean qof_session_load_from_xml_file_v2(FileBackend *, QofBook *);
gboolean qof_session_load_from_xml_file_v2(FileBackend *, QofBook *, QofBookFileType);
/* write all book info to a file */
gboolean gnc_book_write_to_xml_filehandle_v2(QofBook *book, FILE *fh);
@ -142,7 +142,7 @@ gboolean gnc_book_write_accounts_to_xml_file_v2(QofBackend * be, QofBook *book,
/** The is_gncxml_file() routine checks to see if the first few
* chars of the file look like gnc-xml data.
*/
gboolean gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding);
QofBookFileType gnc_is_xml_data_file_v2(const gchar *name, gboolean *with_encoding);
/** Write a name-space declaration for the provided namespace data type
* within the GNC XML namespace at http://www.gnucash.org/XML.

View File

@ -41,6 +41,8 @@ typedef int ssize_t;
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "gnc.backend.file.sixtp"
extern const gchar *gnc_v2_xml_version_string; /* see io-gncxml-v2.c */
/************************************************************************/
gboolean
is_child_result_from_node_named(sixtp_child_result *cr, const char *tag)
@ -860,21 +862,19 @@ search_for(unsigned char marker, char **cursor)
}
}
gboolean
gnc_is_our_xml_file(const char *filename, const char *first_tag,
gboolean *with_encoding)
QofBookFileType
gnc_is_our_xml_file(const char *filename, gboolean *with_encoding)
{
FILE *f = NULL;
char first_chunk[256];
ssize_t num_read;
g_return_val_if_fail(filename, FALSE);
g_return_val_if_fail(first_tag, FALSE);
g_return_val_if_fail(filename, GNC_BOOK_NOT_OURS);
f = g_fopen(filename, "r");
if (f == NULL)
{
return FALSE;
return GNC_BOOK_NOT_OURS;
}
num_read = fread(first_chunk, sizeof(char), sizeof(first_chunk) - 1, f);
@ -882,17 +882,16 @@ gnc_is_our_xml_file(const char *filename, const char *first_tag,
if (num_read == 0)
{
return FALSE;
return GNC_BOOK_NOT_OURS;
}
first_chunk[num_read] = '\0';
return gnc_is_our_first_xml_chunk(first_chunk, first_tag, with_encoding);
return gnc_is_our_first_xml_chunk(first_chunk, with_encoding);
}
gboolean
gnc_is_our_first_xml_chunk(char *chunk, const char *first_tag,
gboolean *with_encoding)
QofBookFileType
gnc_is_our_first_xml_chunk(char *chunk, gboolean *with_encoding)
{
char *cursor = NULL;
@ -905,51 +904,58 @@ gnc_is_our_first_xml_chunk(char *chunk, const char *first_tag,
if (!eat_whitespace(&cursor))
{
return FALSE;
return GNC_BOOK_NOT_OURS;
}
if (strncmp(cursor, "<?xml", 5) == 0)
{
char *tag_compare;
gboolean result;
if (!search_for('>', &cursor))
{
return FALSE;
return GNC_BOOK_NOT_OURS;
}
if (!eat_whitespace(&cursor))
{
return FALSE;
return GNC_BOOK_NOT_OURS;
}
tag_compare = g_strdup_printf("<%s", first_tag);
tag_compare = g_strdup_printf("<%s\n", gnc_v2_xml_version_string);
result = (strncmp(cursor, tag_compare, strlen(tag_compare)) == 0);
g_free (tag_compare);
if (result && with_encoding)
if (strncmp(cursor, tag_compare, strlen(tag_compare)) == 0)
{
*cursor = '\0';
cursor = chunk;
while (search_for('e', &cursor))
if (with_encoding)
{
if (strncmp(cursor, "ncoding=", 8) == 0)
*cursor = '\0';
cursor = chunk;
while (search_for('e', &cursor))
{
*with_encoding = TRUE;
break;
if (strncmp(cursor, "ncoding=", 8) == 0)
{
*with_encoding = TRUE;
break;
}
}
}
g_free (tag_compare);
return GNC_BOOK_XML2_FILE;
}
return result;
}
else
{
return FALSE;
g_free (tag_compare);
if (strncmp(cursor, "<gnc>\n", strlen("<gnc>\n")) == 0)
return GNC_BOOK_XML1_FILE;
/* If it doesn't match any of the above but has '<gnc-v...', it must */
/* be a later version */
if (strncmp(cursor, "<gnc-v", strlen("<gnc-v")) == 0)
return GNC_BOOK_POST_XML2_0_0_FILE;
return GNC_BOOK_NOT_OURS;
}
return FALSE;
return GNC_BOOK_NOT_OURS;
}
/************************* END OF FILE *********************************/

View File

@ -31,6 +31,7 @@
#include "gnc-xml-helper.h"
#include "gnc-engine.h"
#include "gnc-backend-xml.h"
typedef struct _sixtp_child_result sixtp_child_result;
@ -208,11 +209,10 @@ sixtp* sixtp_add_some_sub_parsers(sixtp *tochange, gboolean cleanup, ...);
gboolean sixtp_add_sub_parser(sixtp *parser, const gchar* tag,
sixtp *sub_parser);
gboolean gnc_is_our_xml_file(const char *filename, const char *first_tag,
QofBookFileType gnc_is_our_xml_file(const char *filename,
gboolean *with_encoding);
gboolean gnc_is_our_first_xml_chunk(char *chunk, const char *first_tag,
gboolean *with_encoding);
QofBookFileType gnc_is_our_first_xml_chunk(char *chunk, gboolean *with_encoding);
#endif /* _SIXTP_H_ */

View File

@ -10,6 +10,9 @@
#include "sixtp-utils.h"
#include "sixtp-dom-generators.h"
#define GNC_V2_STRING "gnc-v2"
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
int
main(int argc, char **argv)
{

View File

@ -43,6 +43,9 @@
#include "gnc-commodity.h"
#define GNC_V2_STRING "gnc-v2"
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
static void
test_dom_tree_to_commodity_ref(void)
{

View File

@ -11,6 +11,8 @@
#include "sixtp-dom-generators.h"
#include "sixtp-dom-parsers.h"
#define GNC_V2_STRING "gnc-v2"
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
static void
test_kvp_get_slot(int run,

View File

@ -11,6 +11,9 @@
#include "test-engine-stuff.h"
#include "test-file-stuff.h"
#define GNC_V2_STRING "gnc-v2"
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
static void
test_binary()
{

View File

@ -43,6 +43,9 @@
#include "Account.h"
#include "Scrub.h"
#define GNC_V2_STRING "gnc-v2"
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
static QofBook *sixbook;
static gchar*

View File

@ -24,6 +24,9 @@
#include "Account.h"
#define GNC_V2_STRING "gnc-v2"
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
static QofBook *book;
static gchar*

View File

@ -42,6 +42,9 @@
#include "test-engine-stuff.h"
#include "test-file-stuff.h"
#define GNC_V2_STRING "gnc-v2"
const gchar *gnc_v2_xml_version_string = GNC_V2_STRING;
static QofSession *session;
struct pricedb_data_struct

View File

@ -421,7 +421,8 @@ show_session_error (QofBackendError io_error,
case ERR_SQL_DB_TOO_NEW:
fmt = _("This database is from a newer version of GnuCash. "
"This version can read it, but cannot safely save to it. "
"It will be marked read-only until you do File>Save As.");
"It will be marked read-only until you do File>Save As, "
"but data may be lost in writing to the old version.");
gnc_warning_dialog (parent, "%s", fmt);
uh_oh = TRUE;
break;
@ -458,6 +459,16 @@ show_session_error (QofBackendError io_error,
gnc_error_dialog (parent, "%s", fmt);
break;
case ERR_FILEIO_FILE_UPGRADE:
fmt = _("This file is from an older version of GnuCash and will be "
"upgraded when saved by this version. You will not be able "
"to read the saved file from the older version of Gnucash "
"(it will report an \"error parsing the file\"). If you wish "
"to preserve the old version, exit without saving.");
gnc_warning_dialog (parent, "%s", fmt);
uh_oh = FALSE;
break;
default:
PERR("FIXME: Unhandled error %d", io_error);
fmt = _("An unknown I/O error (%d) occurred.");

View File

@ -98,6 +98,8 @@ typedef enum
ERR_FILEIO_FILE_EACCES, /**< No read access permission for the given file */
ERR_FILEIO_RESERVED_WRITE, /**< User attempt to write to a directory reserved
for internal use by GnuCash */
ERR_FILEIO_FILE_UPGRADE, /**< file will be upgraded and not be able to be
read by prior versions - warn users*/
/* network errors */
ERR_NETIO_SHORT_READ = 2000, /**< not enough bytes received */

View File

@ -1257,6 +1257,7 @@ qof_session_load (QofSession *session,
if ((err != ERR_BACKEND_NO_ERR) &&
(err != ERR_FILEIO_FILE_TOO_OLD) &&
(err != ERR_FILEIO_NO_ENCODING) &&
(err != ERR_FILEIO_FILE_UPGRADE) &&
(err != ERR_SQL_DB_TOO_OLD) &&
(err != ERR_SQL_DB_TOO_NEW))
{