X-Git-Url: http://git.datanom.net/vcard-parser.git/blobdiff_plain/aa039bee0fd8f3db86fb10482345f940ce63f33b..0d68a95569264bb6b305c87c6dfc1c50ad536a79:/src/vcard.c diff --git a/src/vcard.c b/src/vcard.c index 9a09cca..e9881f9 100644 --- a/src/vcard.c +++ b/src/vcard.c @@ -19,12 +19,247 @@ * MA 02110-1301, USA. */ -# include +#include +#include +#include +#include +#include + +#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; }