gnucash maint: Bug 756469 - CSV Invoice Import - Items with double quote escape not imported.

Mike Evans mikee at code.gnucash.org
Thu Jan 14 08:48:11 EST 2016


Updated	 via  https://github.com/Gnucash/gnucash/commit/9b21c9e6 (commit)
	from  https://github.com/Gnucash/gnucash/commit/44814868 (commit)



commit 9b21c9e682e8ade37778f7b67a09bfd0da87355f
Author: Mike Evans <mikee at saxicola.co.uk>
Date:   Thu Jan 14 13:38:11 2016 +0000

    Bug 756469 - CSV Invoice Import - Items with double quote escape not imported.
    
    Update regex to accept escaped quotes in (some) quoted fields. Thanks Derek.
    Convert escaped quotes "" to unescaped " in notes and description fields.

diff --git a/src/plugins/bi_import/dialog-bi-import-gui.c b/src/plugins/bi_import/dialog-bi-import-gui.c
index fa14669..679627f 100644
--- a/src/plugins/bi_import/dialog-bi-import-gui.c
+++ b/src/plugins/bi_import/dialog-bi-import-gui.c
@@ -284,7 +284,7 @@ void gnc_bi_import_gui_filenameChanged_cb (GtkWidget *widget, gpointer data)
 
     // generate preview
     gtk_list_store_clear (gui->store);
-    gnc_bi_import_read_file (filename, gui->regexp->str, gui->store, 10, NULL);
+    gnc_bi_import_read_file (filename, gui->regexp->str, gui->store, 100, NULL);
 
     g_free( filename );
 }
@@ -315,7 +315,7 @@ void gnc_bi_import_gui_option3_cb (GtkWidget *widget, gpointer data)
     BillImportGui *gui = data;
     if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
         return;
-    g_string_assign (gui->regexp, "^((?<id>[^\";]*)|\"(?<id>[^\"]*)\");((?<date_opened>[^\";]*)|\"(?<date_opened>[^\"]*)\");((?<owner_id>[^\";]*)|\"(?<owner_id>[^\"]*)\");((?<billing_id>[^\";]*)|\"(?<billing_id>[^\"]*)\");((?<notes>[^\";]*)|\"(?<notes>[^\"]*)\");((?<date>[^\";]*)|\"(?<date>[^\"]*)\");((?<desc>[^\";]*)|\"(?<desc>[^\"]*)\");((?<action>[^\";]*)|\"(?<action>[^\"]*)\");((?<account>[^\";]*)|\"(?<account>[^\"]*)\");((?<quantity>[^\";]*)|\"(?<quantity>[^\"]*)\");((?<price>[^\";]*)|\"(?<price>[^\"]*)\");((?<disc_type>[^\";]*)|\"(?<disc_type>[^\"]*)\");((?<disc_how>[^\";]*)|\"(?<disc_how>[^\"]*)\");((?<discount>[^\";]*)|\"(?<discount>[^\"]*)\");((?<taxable>[^\";]*)|\"(?<taxable>[^\"]*)\");((?<taxincluded>[^\";]*)|\"(?<taxincluded>[^\"]*)\");((?<tax_table>[^\";]*)|\"(?<tax_table>[^\"]*)\");((?<date_posted>[^\";]*)|\"(?<date_posted>[^\"]*)\");((?<due_date>[^\";]*)|\"(?<due_date>[^\"]*)\");((?<account_posted>[^\";]*)|\"(?<account_posted>[^\"]*)\");((?<memo_posted>[^\";]*)|\"(?<memo_posted>[^\"]*)\");((?<accu_splits>[^\";]*)|\"(?<accu_splits>[^\"]*)\")$");
+    g_string_assign (gui->regexp, "^((?<id>[^\";]*)|\"(?<id>[^\"]*)\");((?<date_opened>[^\";]*)|\"(?<date_opened>[^\"]*)\");((?<owner_id>[^\";]*)|\"(?<owner_id>[^\"]*)\");((?<billing_id>[^\";]*)|\"(?<billing_id>[^\"]*)\");((?<notes>[^\";]*)|\"(?<notes>([^\"]|\"\")*)\");((?<date>[^\";]*)|\"(?<date>[^\"]*)\");((?<desc>[^\";]*)|\"(?<desc>([^\"]|\"\")*)\");((?<action>[^\";]*)|\"(?<action>[^\"]*)\");((?<account>[^\";]*)|\"(?<account>[^\"]*)\");((?<quantity>[^\";]*)|\"(?<quantity>[^\"]*)\");((?<price>[^\";]*)|\"(?<price>[^\"]*)\");((?<disc_type>[^\";]*)|\"(?<disc_type>[^\"]*)\");((?<disc_how>[^\";]*)|\"(?<disc_how>[^\"]*)\");((?<discount>[^\";]*)|\"(?<discount>[^\"]*)\");((?<taxable>[^\";]*)|\"(?<taxable>[^\"]*)\");((?<taxincluded>[^\";]*)|\"(?<taxincluded>[^\"]*)\");((?<tax_table>[^\";]*)|\"(?<tax_table>[^\"]*)\");((?<date_posted>[^\";]*)|\"(?<date_posted>[^\"]*)\");((?<due_date>[^\";]*)|\"(?<due_date>[^\"]*)\");((?<account_posted>[^\";]*)|\"(?<account_posted>[^\"]*)\");((?<memo_posted>[^\";]*)|\"(?<memo_posted>[^\"]*)\");((?<accu_splits>[^\";]*)|\"(?<accu_splits>[^\"]*)\")$");
     gnc_bi_import_gui_filenameChanged_cb (gui->entryFilename, gui);
 }
 
@@ -325,7 +325,7 @@ void gnc_bi_import_gui_option4_cb (GtkWidget *widget, gpointer data)
     BillImportGui *gui = data;
     if (!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(widget) ))
         return;
-    g_string_assign (gui->regexp, "^((?<id>[^\",]*)|\"(?<id>[^\"]*)\"),((?<date_opened>[^\",]*)|\"(?<date_opened>[^\"]*)\"),((?<owner_id>[^\",]*)|\"(?<owner_id>[^\"]*)\"),((?<billing_id>[^\",]*)|\"(?<billing_id>[^\"]*)\"),((?<notes>[^\",]*)|\"(?<notes>[^\"]*)\"),((?<date>[^\",]*)|\"(?<date>[^\"]*)\"),((?<desc>[^\",]*)|\"(?<desc>[^\"]*)\"),((?<action>[^\",]*)|\"(?<action>[^\"]*)\"),((?<account>[^\",]*)|\"(?<account>[^\"]*)\"),((?<quantity>[^\",]*)|\"(?<quantity>[^\"]*)\"),((?<price>[^\",]*)|\"(?<price>[^\"]*)\"),((?<disc_type>[^\",]*)|\"(?<disc_type>[^\"]*)\"),((?<disc_how>[^\",]*)|\"(?<disc_how>[^\"]*)\"),((?<discount>[^\",]*)|\"(?<discount>[^\"]*)\"),((?<taxable>[^\",]*)|\"(?<taxable>[^\"]*)\"),((?<taxincluded>[^\",]*)|\"(?<taxincluded>[^\"]*)\"),((?<tax_table>[^\",]*)|\"(?<tax_table>[^\"]*)\"),((?<date_posted>[^\",]*)|\"(?<date_posted>[^\"]*)\"),((?<due_date>[^\",]*)|\"(?<due_date>[^\"]*)\"),((?<account_posted>[^\",]*)|\"(?<account_posted>[^\"]*)\"),((?<memo_posted>[^\",]*)|\"(?<memo_posted>[^\"]*)\"),((?<accu_splits>[^\",]*)|\"(?<accu_splits>[^\"]*)\")$");
+    g_string_assign (gui->regexp, "^((?<id>[^\",]*)|\"(?<id>[^\"]*)\"),((?<date_opened>[^\",]*)|\"(?<date_opened>[^\"]*)\"),((?<owner_id>[^\",]*)|\"(?<owner_id>[^\"]*)\"),((?<billing_id>[^\",]*)|\"(?<billing_id>[^\"]*)\"),((?<notes>[^\",]*)|\"(?<notes>([^\"]|\"\")*)\"),((?<date>[^\",]*)|\"(?<date>[^\"]*)\"),((?<desc>[^\",]*)|\"(?<desc>([^\"]|\"\")*)\"),((?<action>[^\",]*)|\"(?<action>[^\"]*)\"),((?<account>[^\",]*)|\"(?<account>[^\"]*)\"),((?<quantity>[^\",]*)|\"(?<quantity>[^\"]*)\"),((?<price>[^\",]*)|\"(?<price>[^\"]*)\"),((?<disc_type>[^\",]*)|\"(?<disc_type>[^\"]*)\"),((?<disc_how>[^\",]*)|\"(?<disc_how>[^\"]*)\"),((?<discount>[^\",]*)|\"(?<discount>[^\"]*)\"),((?<taxable>[^\",]*)|\"(?<taxable>[^\"]*)\"),((?<taxincluded>[^\",]*)|\"(?<taxincluded>[^\"]*)\"),((?<tax_table>[^\",]*)|\"(?<tax_table>[^\"]*)\"),((?<date_posted>[^\",]*)|\"(?<date_posted>[^\"]*)\"),((?<due_date>[^\",]*)|\"(?<due_date>[^\"]*)\"),((?<account_posted>[^\",]*)|\"(?<account_posted>[^\"]*)\"),((?<memo_posted>[^\",]*)|\"(?<memo_posted>[^\"]*)\"),((?<accu_splits>[^\",]*)|\"(?<accu_splits>[^\"]*)\")$");
     gnc_bi_import_gui_filenameChanged_cb (gui->entryFilename, gui);
 }
 
diff --git a/src/plugins/bi_import/dialog-bi-import.c b/src/plugins/bi_import/dialog-bi-import.c
index a67d255..f9eb832 100644
--- a/src/plugins/bi_import/dialog-bi-import.c
+++ b/src/plugins/bi_import/dialog-bi-import.c
@@ -79,7 +79,7 @@
             }
 
 static QofLogModule log_module = G_LOG_DOMAIN; //G_LOG_BUSINESS;
-
+static char * un_escape(char *str);
 bi_import_result
 gnc_bi_import_read_file (const gchar * filename, const gchar * parser_regexp,
                          GtkListStore * store, guint max_rows,
@@ -240,9 +240,9 @@ gnc_bi_import_fix_bis (GtkListStore * store, guint * fixed, guint * deleted,
     guint dummy;
     gint row = 1;
     const gchar* date_format_string = qof_date_format_get_string (qof_date_format_get()); // Get the user set date format string
-    
-    
-    //date_format_string = qof_date_format_get_string (qof_date_format_get());	
+
+
+    //date_format_string = qof_date_format_get_string (qof_date_format_get());
 
     DEBUG("date_format_string: %s",date_format_string);
     // allow the call to this function with only GtkListeStore* specified
@@ -298,7 +298,7 @@ gnc_bi_import_fix_bis (GtkListStore * store, guint * fixed, guint * deleted,
                                     row, id);
         }
         else
-        {   // TODO: If id is empty get the next one in the series.  Bug 731105 
+        {   // TODO: If id is empty get the next one in the series.  Bug 731105
             if (strlen (id) == 0)
             {
                 // no invoice id specified
@@ -386,9 +386,9 @@ gnc_bi_import_fix_bis (GtkListStore * store, guint * fixed, guint * deleted,
                 gtk_list_store_set (store, &iter, DUE_DATE,
                                         date_posted, -1);
                 row_fixed = TRUE;
-                
+
             }
-            
+
             // due_date is valid
             */
             if (strlen (quantity) == 0)
@@ -397,7 +397,7 @@ gnc_bi_import_fix_bis (GtkListStore * store, guint * fixed, guint * deleted,
                 gtk_list_store_set (store, &iter, QUANTITY, "1", -1);
                 row_fixed = TRUE;
             }
-            
+
 
             // quantity is valid
 
@@ -533,7 +533,7 @@ gnc_bi_import_create_bis (GtkListStore * store, QofBook * book,
     gchar *new_id = NULL;
     gint64 denom = 0;
     gnc_commodity *currency;
-    
+
     // these arguments are needed
     g_return_if_fail (store && book);
     // logic of this function only works for bills or invoices
@@ -626,6 +626,7 @@ gnc_bi_import_create_bis (GtkListStore * store, QofBook * book,
                 gncInvoiceSetDateOpened (invoice, now_timespec);
             }
             gncInvoiceSetBillingID (invoice, billing_id ? billing_id : "");
+            notes = un_escape(notes);
             gncInvoiceSetNotes (invoice, notes ? notes : "");
             gncInvoiceSetActive (invoice, TRUE);
             //if (g_ascii_strcasecmp(type,"INVOICE"))gncInvoiceSetBillTo( invoice, billto );
@@ -710,6 +711,9 @@ gnc_bi_import_create_bis (GtkListStore * store, QofBook * book,
         }
         timespecFromTime64 (&today, gnc_time (NULL));	// set today to the current date
         gncEntrySetDateEntered (entry, today);
+        // Remove escaped quotes
+        desc = un_escape(desc);
+        notes = un_escape(notes);
         gncEntrySetDescription (entry, desc);
         gncEntrySetAction (entry, action);
         value = gnc_numeric_zero();
@@ -717,7 +721,7 @@ gnc_bi_import_create_bis (GtkListStore * store, QofBook * book,
         gncEntrySetQuantity (entry, value);
         acc = gnc_account_lookup_for_register (gnc_get_current_root_account (),
                                                account);
-        
+
         if (g_ascii_strcasecmp (type, "BILL") == 0)
         {
             gncEntrySetBillAccount (entry, acc);
@@ -751,8 +755,8 @@ gnc_bi_import_create_bis (GtkListStore * store, QofBook * book,
         valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter);
 
         // handle auto posting of invoices
-    
-        
+
+
         if (valid)
             gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, ID, &new_id, -1);
         if (g_strcmp0 (id, new_id) != 0)
@@ -782,8 +786,8 @@ gnc_bi_import_create_bis (GtkListStore * store, QofBook * book,
             }
 
         }
-        
-        
+
+
     }
     // cleanup
     g_free (new_id);
@@ -809,5 +813,36 @@ gnc_bi_import_create_bis (GtkListStore * store, QofBook * book,
     g_free (account_posted);
     g_free (memo_posted);
     g_free (accumulatesplits);
-    
+
+}
+
+/* Change any escaped quotes ("") to (")
+ * @param char* String to be modified
+ * @return char* Modified string.
+*/
+static char * un_escape(char *str)
+{
+    gchar quote = '"';
+    gchar *newStr = NULL;
+    int n = 0;
+    newStr = g_malloc(strlen(str)+1); // This must be freed in the calling code.
+    while(*str != '\0')
+    {
+        if(*str == quote)
+        {
+            str++;
+            if(*str == quote)
+            {
+                newStr[n] = quote;
+            }
+        }
+        else
+        {
+            newStr[n] = *str;
+        }
+            str++;
+            n++;
+        }
+	newStr[n] = '\0'; //ending the character array
+    return newStr;
 }



Summary of changes:
 src/plugins/bi_import/dialog-bi-import-gui.c |  6 +--
 src/plugins/bi_import/dialog-bi-import.c     | 65 +++++++++++++++++++++-------
 2 files changed, 53 insertions(+), 18 deletions(-)



More information about the gnucash-changes mailing list