-# include <vcard.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <globals.h>
+#include "vcard.h"
+
+int main(int argc, char *argv[]) {
+ GError* err = NULL;
+ gchar* buffer = NULL;
+ int args;
+
+ if (argc > 1) {
+ for (args = 1; args < argc; args++) {
+ g_file_get_contents(argv[args], &buffer, NULL, &err);
+
+ if (err) {
+ fprintf(stderr, "%s\n", err->message);
+ g_error_free(err);
+ return 1;
+ }
+
+ GSList* list = VCard_new_from_text(buffer, VCARD_VERSION_DETECT, FALSE);
+ g_free(buffer);
+ buffer = NULL;
+ GSList* tmp = list;
+ while (tmp) {
+ VCard* vc = (VCard*) tmp->data;
+ gchar* state = VCard_get_state(vc);
+ if (g_strcmp0("OK", state) != 0)
+ fprintf(stderr, "%s\n", state);
+ g_free(state);
+
+ g_print("Search property ADR in vCard\n");
+ GSList* prop = VCard_get_property(vc, "ADR");
+ for (GSList* iter = prop; iter; iter = g_slist_next(iter)) {
+ gchar* s = (gchar*) iter->data;
+ g_print("%s\n", s);
+ g_free(s);
+ }
+ g_slist_free(prop);
+ tmp = tmp->next;
+ }
+ VCard_print_list(list);
+ g_print("\n");
+ VCard_list_free(list);
+ }
+ } else {
+ g_print("Mising file argument(s)\n");
+ g_print("Usage: %s file [file ..]\n", argv[0]);
+ }
-int main() {
return 0;
}
* MA 02110-1301, USA.
*/
-#ifndef __VCARD_H__
-#define __VCARD_H__
+#ifndef __VCARD_PARSER_H__
+#define __VCARD_PARSER_H__
#include <glib.h>
G_BEGIN_DECLS
+#include <globals.h>
+
typedef enum {
// vCard 2.1 properties and up
+ // https://github.com/emacsmirror/addressbook/blob/master/vcard-21.txt
N = 0,
FN,
PHOTO,
VERSION,
KEY,
TZ,
+ SOURCE,
+ AGENT, // Removed in vCard 4.0
+ PROFILE, // Removed in vCard 4.0
// vCard 3.0 properties
+ // https://tools.ietf.org/html/rfc2426
CATEGORIES,
SORT_STRING,
PRODID,
NICKNAME,
+ NAME, // Removed in vCard 4.0
CLASS, // Removed in vCard 4.0
// rfc2739 properties
FBURL,
// rfc4770 properties
IMPP,
// vCard 4.0 properties
- SOURCE,
+ // https://tools.ietf.org/html/rfc6350
XML,
ANNIVERSARY,
CLIENTPIDMAP,
VCARD_PROPERTIES,
} Property;
-gchar* Proterties[VCARD_PROPERTIES+1] = {
- "N",
- "FN",
- "PHOTO",
- "BDAY",
- "ADR",
- "LABEL",
- "TEL",
- "EMAIL",
- "MAILER",
- "GEO",
- "TITLE",
- "ROLE",
- "LOGO",
- "ORG",
- "NOTE",
- "REV",
- "SOUND",
- "URL",
- "UID",
- "VERSION",
- "KEY",
- "TZ",
- "CATEGORIES",
- "SORT-STRING",
- "PRODID",
- "NICKNAME",
- "CLASS",
- "FBURL",
- "CAPURI",
- "CALURI",
- "CALADRURI",
- "IMPP",
- "SOURCE",
- "XML",
- "ANNIVERSARY",
- "CLIENTPIDMAP",
- "LANG",
- "GENDER",
- "KIND",
- "MEMBER",
- "RELATED",
- "BIRTHPLACE",
- "DEATHPLACE",
- "DEATHDATE",
- "EXPERTISE",
- "HOBBY",
- "INTEREST",
- "ORG-DIRECTORY",
- NULL
-};
+typedef enum {
+ VCARD_PARSER_OK,
+ VCARD_PARSER_VERSION_MISSING,
+ VCARD_PARSER_VERSION_MISMATCH,
+ VCARD_PARSER_ATTRIBUTE_VERSION_MISMATCH,
+ VCARD_PARSER_BAD_FORMAT,
+ VCARD_PARSER_ERROR,
+} VCardParserResponse;
-G_END_DECLS
+typedef struct {
+ gchar* name;
+ gchar* value;
+} VCardProperty;
+
+VCardVersion str_2_vcard_version(const gchar* version);
+gchar* vcard_version_2_str(VCardVersion version);
+Property vcard_max_property(VCardVersion version);
+VCardParserResponse vcard_parse_text(const gchar* text, VCardVersion* version, GHashTable** vcard);
+void destroy_hash_table(GHashTable* ht);
-gboolean vcard_parse_text();
+G_END_DECLS
#endif
* MA 02110-1301, USA.
*/
-# include <vcard.h>
+#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 {
- gchar *version;
+ VCardParserResponse state;
+ VCardVersion version;
+ GHashTable* vcard;
};
-int main() {
- return 0;
+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;
}
* MA 02110-1301, USA.
*/
-#ifndef __VCARD_PARSER_H__
-#define __VCARD_PARSER_H__
+#ifndef __VCARD_H__
+#define __VCARD_H__
#include <glib.h>
G_BEGIN_DECLS
#include <stdio.h>
-#include <vcard-parser.h>
+#include <globals.h>
-typedef enum {
- DETECT,
- VERSION_2_1,
- VERSION_3_0,
- VERSION_4_0,
-} VCardVersion;
+//VCard* VCard_new(VCardVersion version);
+GSList* VCard_new_from_text(const gchar* text, VCardVersion version, gboolean skip_broken);
+GSList* VCard_new_from_file(FILE* file, VCardVersion version, gboolean skip_broken);
+void VCard_free(VCard* object);
+void VCard_list_free(GSList* list);
-typedef struct _VCard VCard;
-
-VCard* VCard_new(VCardVersion version);
-VCard* VCard_new_from_text(const gchar* text, VCardVersion version);
-VCard* VCard_new_from_file(FILE* file, VCardVersion version);
+void VCard_print_list(GSList* list);
+void VCard_print_list_fd(GSList* list, int fd);
void VCard_print(VCard* object);
void VCard_print_fd(VCard* object, int fd);
+gchar* VCard_get_state(VCard* object);
+GSList* VCard_get_property(VCard* object, const gchar* property);
G_END_DECLS