r20382 - gnucash/trunk/src/libqof/qof - Bug #644036: Counter format validation fails on Windows because the number format is I64i there.

Christian Stimming cstim at code.gnucash.org
Tue Mar 8 06:15:08 EST 2011


Author: cstim
Date: 2011-03-08 06:15:07 -0500 (Tue, 08 Mar 2011)
New Revision: 20382
Trac: http://svn.gnucash.org/trac/changeset/20382

Modified:
   gnucash/trunk/src/libqof/qof/qofbook-p.h
   gnucash/trunk/src/libqof/qof/qofbook.c
   gnucash/trunk/src/libqof/qof/test/test-qof.c
   gnucash/trunk/src/libqof/qof/test/test-qofbook.c
Log:
Bug #644036: Counter format validation fails on Windows because the number format is I64i there.

Note: Users will run into a problem when copying a windows file to linux
and vice versa because the counter format will have to be changed on the
other operating system each time.

Modified: gnucash/trunk/src/libqof/qof/qofbook-p.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbook-p.h	2011-03-07 19:23:26 UTC (rev 20381)
+++ gnucash/trunk/src/libqof/qof/qofbook-p.h	2011-03-08 11:15:07 UTC (rev 20382)
@@ -61,6 +61,14 @@
 #define qof_book_set_guid(book,guid)    \
          qof_instance_set_guid(QOF_INSTANCE(book), guid)
 
+/** Validate a counter format string with the given
+ *    G_GINT64_FORMAT. Returns an error message if the format string
+ *    was invalid, or NULL if it is ok. The caller should free the
+ *    error message with g_free.
+ */
+gchar *qof_book_validate_counter_format_internal(const gchar *p,
+        const gchar* gint64_format);
+
 /* @} */
 /* @} */
 /* @} */

Modified: gnucash/trunk/src/libqof/qof/qofbook.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbook.c	2011-03-07 19:23:26 UTC (rev 20381)
+++ gnucash/trunk/src/libqof/qof/qofbook.c	2011-03-08 11:15:07 UTC (rev 20382)
@@ -563,8 +563,15 @@
 gchar *
 qof_book_validate_counter_format(const gchar *p)
 {
-    const gchar *conv_start, *tmp;
+    return qof_book_validate_counter_format_internal(p, G_GINT64_FORMAT);
+}
 
+gchar *
+qof_book_validate_counter_format_internal(const gchar *p,
+        const gchar *gint64_format)
+{
+    const gchar *conv_start, *tmp = NULL;
+
     /* Validate a counter format. This is a very simple "parser" that
      * simply checks for a single gint64 conversion specification,
      * allowing all modifiers and flags that printf(3) specifies (except
@@ -597,11 +604,23 @@
     /* Skip the % */
     p++;
 
+    /* See whether we have already reached the correct format
+     * specification (e.g. "li" on Unix, "I64i" on Windows). */
+    tmp = strstr(p, gint64_format);
+
     /* Skip any number of flag characters */
-    while (*p && strchr("#0- +'I", *p)) p++;
+    while (*p && (tmp != p) && strchr("#0- +'I", *p))
+    {
+        p++;
+        tmp = strstr(p, gint64_format);
+    }
 
     /* Skip any number of field width digits */
-    while (*p && strchr("0123456789", *p)) p++;
+    while (*p && (tmp != p) && strchr("0123456789", *p))
+    {
+        p++;
+        tmp = strstr(p, gint64_format);
+    }
 
     /* A precision specifier always starts with a dot */
     if (*p && *p == '.')
@@ -617,10 +636,10 @@
 
     /* See if the format string starts with the correct format
      * specification. */
-    tmp = strstr(p, G_GINT64_FORMAT);
+    tmp = strstr(p, gint64_format);
     if (tmp == NULL)
     {
-        return g_strdup_printf("Invalid length modifier and/or conversion specifier ('%.2s'), it should be: " G_GINT64_FORMAT, p);
+        return g_strdup_printf("Invalid length modifier and/or conversion specifier ('%.4s'), it should be: %s", p, gint64_format);
     }
     else if (tmp != p)
     {
@@ -628,7 +647,7 @@
     }
 
     /* Skip length modifier / conversion specifier */
-    p += strlen(G_GINT64_FORMAT);
+    p += strlen(gint64_format);
 
     /* Skip a suffix of any character except % */
     while (*p)

Modified: gnucash/trunk/src/libqof/qof/test/test-qof.c
===================================================================
--- gnucash/trunk/src/libqof/qof/test/test-qof.c	2011-03-07 19:23:26 UTC (rev 20381)
+++ gnucash/trunk/src/libqof/qof/test/test-qof.c	2011-03-08 11:15:07 UTC (rev 20382)
@@ -36,6 +36,7 @@
     g_type_init(); 			/* Initialize the GObject system */
     g_test_init ( &argc, &argv, NULL ); 	/* initialize test program */
     qof_log_init_filename_special("/dev/null"); /* Init the log system */
+    g_test_bug_base("https://bugzilla.gnome.org/show_bug.cgi?id="); /* init the bugzilla URL */
 
     test_suite_qofbook();
     test_suite_qofinstance();

Modified: gnucash/trunk/src/libqof/qof/test/test-qofbook.c
===================================================================
--- gnucash/trunk/src/libqof/qof/test/test-qofbook.c	2011-03-07 19:23:26 UTC (rev 20381)
+++ gnucash/trunk/src/libqof/qof/test/test-qofbook.c	2011-03-08 11:15:07 UTC (rev 20382)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <glib.h>
 #include <qof.h>
+#include "qofbook-p.h"
 
 static const gchar *suitename = "/qof/qofbook";
 void test_suite_qofbook ( void );
@@ -52,9 +53,70 @@
     qof_book_mark_readonly( fixture->book );
     g_assert( qof_book_is_readonly( fixture->book ) );
 }
+static void
+test_book_validate_counter( void )
+{
+    gchar *r;
+    g_test_bug("644036");
 
+    /* Test for detection of missing format conversion */
+    r = qof_book_validate_counter_format("This string is missing the conversion specifier");
+    g_assert(r);
+    if (r && g_test_verbose())
+    {
+        g_test_message("Counter format validation correctly failed: %s", r);
+    }
+    g_free(r);
+
+    /* Test the usual Linux/Unix G_GINT64_FORMAT */
+    r = qof_book_validate_counter_format_internal("Test - %li", "li");
+    if (r && g_test_verbose())
+    {
+        g_test_message("Counter format validation erroneously failed: %s", r);
+    }
+    g_assert(r == NULL);
+    g_free(r);
+
+    /* Test the Windows G_GINT64_FORMAT */
+    r = qof_book_validate_counter_format_internal("Test - %I64i", "I64i");
+    if (r && g_test_verbose())
+    {
+        g_test_message("Counter format validation erroneously failed: %s", r);
+    }
+    g_assert(r == NULL);
+    g_free(r);
+
+    /* Test the system's GINT64_FORMAT */
+    r = qof_book_validate_counter_format("Test - %" G_GINT64_FORMAT);
+    if (r && g_test_verbose())
+    {
+        g_test_message("Counter format validation erroneously failed: %s", r);
+    }
+    g_assert(r == NULL);
+    g_free(r);
+
+    /* Test an erroneous Windows G_GINT64_FORMAT */
+    r = qof_book_validate_counter_format_internal("Test - %li", "I64i");
+    if (r && g_test_verbose())
+    {
+        g_test_message("Counter format validation correctly failed: %s", r);
+    }
+    g_assert(r);
+    g_free(r);
+
+    /* Test an erroneous Linux G_GINT64_FORMAT */
+    r = qof_book_validate_counter_format_internal("Test - %I64i", "li");
+    if (r && g_test_verbose())
+    {
+        g_test_message("Counter format validation correctly failed: %s", r);
+    }
+    g_assert(r);
+    g_free(r);
+}
+
 void
 test_suite_qofbook ( void )
 {
     g_test_add( suitename, Fixture, NULL, setup, test_book_readonly, teardown );
+    g_test_add_func( suitename, test_book_validate_counter );
 }



More information about the gnucash-changes mailing list