[balsa/gtk3] Allow for quoted strings in vcal items



commit ca68972af1db0f7f71620e27bf4b960e1ae88d99
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Sun Feb 8 19:58:54 2015 -0500

    Allow for quoted strings in vcal items
    
        * libbalsa/rfc2445.c (vcal_strchr): replacement for strchr that
        ignores matches in quoted strings;
        (vcal_strsplit_at_char): replacement for g_strsplit that uses
        vcal_strchr;
        (libbalsa_vcal_new_from_body): use them.

 ChangeLog          |   10 ++++++++++
 libbalsa/rfc2445.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 60 insertions(+), 2 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2f2d580..b71de85 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2015-02-08  Peter Bloomfield  <pbloomfield bellsouth net>
+
+       Allow for quoted strings in vcal items
+
+       * libbalsa/rfc2445.c (vcal_strchr): replacement for strchr that
+       ignores matches in quoted strings;
+       (vcal_strsplit_at_char): replacement for g_strsplit that uses
+       vcal_strchr;
+       (libbalsa_vcal_new_from_body): use them.
+
 2015-02-03  Peter Bloomfield  <pbloomfield bellsouth net>
 
        Simplify BalsaMailboxConfView destruction
diff --git a/libbalsa/rfc2445.c b/libbalsa/rfc2445.c
index fd2dbf0..fe208f8 100644
--- a/libbalsa/rfc2445.c
+++ b/libbalsa/rfc2445.c
@@ -245,6 +245,54 @@ libbalsa_vevent_new(void)
         s = text_2445_unescape(v);              \
     } while (0)
 
+/*
+ * Find the first occurrence of c in s that is not in a double-quoted
+ * string.
+ *
+ * Note that if c is '\0', the return value is NULL, *not* a pointer to
+ * the terminating '\0' (c.f. strchr).
+ */
+static gchar *
+vcal_strchr(gchar * s, gint c)
+{
+    gboolean is_quoted = FALSE;
+
+    while (*s) {
+        if (*s == '"')
+            is_quoted = !is_quoted;
+        else if (*s == c && !is_quoted)
+            return s;
+        ++s;
+    }
+
+    return NULL;
+}
+
+/*
+ * Split the string s at unquoted occurrences of c.
+ *
+ * Note that c is a single character, not a string, as in g_strsplit,
+ * and that there is no limit on the number of splits.
+ *
+ * Returns a newly-allocated NULL-terminated array of strings. Use
+ * g_strfreev() to free it.
+ */
+static gchar **
+vcal_strsplit_at_char(gchar * s, gint c)
+{
+    GPtrArray *array = g_ptr_array_new();
+    gchar *p;
+
+    while ((p = vcal_strchr(s, c))) {
+        g_ptr_array_add(array, g_strndup(s, p - s));
+        s = p + 1;
+    }
+    g_ptr_array_add(array, g_strdup(s));
+    g_ptr_array_add(array, NULL);
+
+    return (gchar **) g_ptr_array_free(array, FALSE);
+}
+
 /* parse a text/calendar part and convert it into a LibBalsaVCal object */
 LibBalsaVCal *
 libbalsa_vcal_new_from_body(LibBalsaMessageBody * body)
@@ -314,12 +362,12 @@ libbalsa_vcal_new_from_body(LibBalsaMessageBody * body)
            if (!g_ascii_strcasecmp("BEGIN:VEVENT", lines[k]))
                event = libbalsa_vevent_new();
        } else if (strlen(lines[k])) {
-           gchar *value = strchr(lines[k], ':');
+           gchar *value = vcal_strchr(lines[k], ':');
            gchar **entry;
 
            if (value)
                *value++ = '\0';
-           entry = g_strsplit(lines[k], ";", -1);
+           entry = vcal_strsplit_at_char(lines[k], ';');
            if (!g_ascii_strcasecmp(entry[0], "END")) {
                 if (value && !g_ascii_strcasecmp(value, "VEVENT")) {
                     retval->vevent = g_list_append(retval->vevent, event);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]