]> git.datanom.net - vcard-parser.git/blobdiff - src/vcard.c
Completed initialization
[vcard-parser.git] / src / vcard.c
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e9881f91d85aaf526e68a5d8cb3d391f90a801c3 100644 (file)
@@ -0,0 +1,265 @@
+/*
+ * vcard.c
+ *
+ * Copyright 2019 Michael Rasmussen <mir@datanom.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <glib/gprintf.h>
+#include <vcard.h>
+#include <vcard-parser.h>
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+struct _VCard {
+       VCardParserResponse     state;
+       VCardVersion            version;
+       GHashTable*                     vcard;
+};
+
+static char *replaceWord(const char *s, const char *oldW, const char *newW) {
+    char *result;
+    int i, cnt = 0;
+    int newWlen = strlen(newW);
+    int oldWlen = strlen(oldW);
+
+    for (i = 0; s[i] != '\0'; i++) {
+        if (strstr(&s[i], oldW) == &s[i]) {
+            cnt++;
+            i += oldWlen - 1;
+        }
+    }
+
+    result = (char *) malloc(i + cnt * (newWlen - oldWlen) + 1);
+
+    i = 0;
+    while (*s) {
+        if (strstr(s, oldW) == s) {
+            strcpy(&result[i], newW);
+            i += newWlen;
+            s += oldWlen;
+        }
+        else
+            result[i++] = *s++;
+    }
+
+    result[i] = '\0';
+    return result;
+}
+
+static void hash_table_cb(gpointer key, gpointer value, gpointer data) {
+       GSList* list = (GSList*) value;
+       gchar** str = (gchar**) data;
+       gchar* s = NULL;
+
+       if (!list) return;
+
+       while (list) {
+               VCardProperty* vp = (VCardProperty*) list->data;
+               gchar* s0 = replaceWord(vp->value, "\n", "\n ");
+               if (!*str)
+                       s = g_strconcat(vp->name, ":", s0, NULL);
+               else {
+                       s = g_strconcat(*str, "\n", vp->name, ":", s0, NULL);
+                       g_free(*str);
+               }
+               g_free(s0);
+               *str = g_strdup(s);
+               g_free(s);
+               list = list->next;
+       }
+}
+
+static gchar** make_chunks(const gchar* text) {
+       gchar** chunks = NULL;
+       gchar* v_text = g_strdup(text);
+       g_strstrip(v_text);
+
+       gchar** tmp = g_strsplit(v_text, "END:VCARD", 0);
+       g_free(v_text);
+       guint lines = g_strv_length(tmp);
+       if (lines < 2)
+               return tmp;
+
+       if (strlen(tmp[lines-1]) < 1) {
+               chunks = g_new0(gchar*, lines);
+               lines--;
+       } else
+               chunks = g_new0(gchar*, lines + 1);
+
+       for(int i = 0; i < lines; i++) {
+               g_strchug(tmp[i]);
+               chunks[i] = g_strconcat(tmp[i], "END:VCARD", NULL);
+       }
+       g_strfreev(tmp);
+
+       return chunks;
+}
+
+void VCard_free(VCard* object) {
+       if (object == NULL) return;
+
+       if (object->vcard)
+               destroy_hash_table(object->vcard);
+       g_free(object);
+}
+
+void VCard_list_free(GSList* list) {
+       GSList* tmp = list;
+
+       while(tmp) {
+               VCard* object = (VCard*) tmp->data;
+               VCard_free(object);
+               tmp = tmp->next;
+       }
+
+       if(list)
+               g_slist_free(list);
+}
+
+/*
+VCard* VCard_new(VCardVersion version) {
+       VCard* vc = g_new0(VCard, 1);
+       vc->version = version;
+
+       return vc;
+}
+*/
+
+GSList* VCard_new_from_text(const gchar* text, VCardVersion version, gboolean skip_broken) {
+       GSList* list = NULL;
+       VCard* vc = NULL;
+
+       if (!text || strlen(text) < 1) return NULL;
+
+       gchar** chunks = make_chunks(text);
+       for (int i =  0; i < g_strv_length(chunks); i++) {
+               vc = g_new0(VCard, 1);
+               vc->version = version;
+
+               VCardParserResponse r = vcard_parse_text(chunks[i], &vc->version, &vc->vcard);
+               if (r != VCARD_PARSER_OK && skip_broken) {
+                       VCard_free(vc);
+                       continue;
+               }
+               vc->state = r;
+               list = g_slist_prepend(list, vc);
+       }
+       g_strfreev(chunks);
+
+       return list;
+}
+
+GSList* VCard_new_from_file(FILE* file, VCardVersion version, gboolean skip_broken) {
+       GSList* list = NULL;
+       VCard* vc = g_new0(VCard, 1);
+
+       vc->version = version;
+       list = g_slist_prepend(list, vc);
+
+       return list;
+}
+
+void VCard_print_list(GSList* list) {
+       VCard_print_list_fd(list, STDOUT_FILENO);
+}
+
+void VCard_print_list_fd(GSList* list, int fd) {
+       GSList* tmp = list;
+       if (fd > 0) {
+               while(tmp) {
+                       VCard* object = (VCard*) tmp->data;
+                       VCard_print_fd(object, fd);
+                       if (tmp->next) {
+                               ssize_t len = strlen("\n");
+                               if (write(fd, "\n", len) < len)
+                                       g_warning(strerror(errno));
+                       }
+                       tmp = tmp->next;
+               }
+       }
+}
+
+void VCard_print(VCard* object){
+       VCard_print_fd(object, STDOUT_FILENO);
+}
+
+void VCard_print_fd(VCard* object, int fd) {
+       gchar *body = NULL, *s = NULL;
+
+       if (object && object->vcard && fd > 0) {
+               gchar* version = vcard_version_2_str(object->version);
+               s = g_strdup_printf("BEGIN:VCARD\nVERSION:%s", version);
+               g_free(version);
+               g_hash_table_foreach(object->vcard, hash_table_cb, &s);
+               body = g_strdup_printf("%s\nEND:VCARD", s);
+               g_free(s);
+               ssize_t len = strlen(body);
+               if (write(fd, body, len) < len)
+                       g_warning(strerror(errno));
+               g_free(body);
+       }
+}
+
+gchar* VCard_get_state(VCard* object) {
+       gchar* message = NULL;
+
+       if (!object) return NULL;
+
+       switch (object->state) {
+               case VCARD_PARSER_OK:
+                       message = g_strdup("OK");
+                       break;
+               case VCARD_PARSER_VERSION_MISMATCH:
+                       message = g_strdup("Version mismatch");
+                       break;
+               case VCARD_PARSER_ATTRIBUTE_VERSION_MISMATCH:
+                       message = g_strdup("Attribute not supported in this version");
+                       break;
+               case VCARD_PARSER_BAD_FORMAT:
+                       message = g_strdup("Bad input format");
+                       break;
+               case VCARD_PARSER_ERROR:
+                       message = g_strdup("Unknown error");
+                       break;
+               default:
+                       message = g_strdup("Unhandled error");
+                       break;
+       }
+
+       return message;
+}
+
+GSList* VCard_get_property(VCard* object, const gchar* property) {
+       GSList *values = NULL, *tmp;
+       GSList *iter;
+       VCardProperty* vp = NULL;
+
+       if (object && object->vcard && property) {
+               tmp = g_hash_table_lookup(object->vcard, property);
+               for (iter = tmp; iter; iter = g_slist_next(iter)) {
+                       vp = (VCardProperty*) iter->data;
+                       values = g_slist_prepend(values, g_strdup_printf("%s:%s", vp->name, vp->value));
+        }
+       }
+
+       return values;
+}
This page took 0.043039 seconds and 5 git commands to generate.