/* * Evolution CSV and TAB importer * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) version 3. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with the program; if not, see * * * Authors: * Devashish Sharma * * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) * */ #include #include #include #include #include #include #include #include #include #include #include "e-util/e-import.h" #include "evolution-addressbook-importers.h" #define NOMAP -1 #define EVOLUTION_IMPORTER 3 #define MOZILLA_IMPORTER 2 #define OUTLOOK_IMPORTER 1 #define CSV_FILE_DELIMITER ',' #define TAB_FILE_DELIMITER '\t' typedef struct { EImport *import; EImportTarget *target; guint idle_id; gint state; FILE *file; gulong size; gint count; EBook *book; GSList *contacts; } CSVImporter; static gint importer; static gchar delimiter; static void csv_import_done(CSVImporter *gci); typedef struct { const gchar *csv_attribute; EContactField contact_field; #define FLAG_HOME_ADDRESS 0x01 #define FLAG_WORK_ADDRESS 0x02 #define FLAG_OTHER_ADDRESS 0x04 #define FLAG_STREET 0x08 #define FLAG_CITY 0x10 #define FLAG_STATE 0x20 #define FLAG_POSTAL_CODE 0x40 #define FLAG_COUNTRY 0x80 #define FLAG_POBOX 0x70 #define FLAG_DATE_BDAY 0x03 #define FLAG_BIRTH_DAY 0x05 #define FLAG_BIRTH_YEAR 0x07 #define FLAG_BIRTH_MONTH 0x50 #define FLAG_DATE_ANNIVERSARY 0x30 #define FLAG_INVALID 0xff gint flags; }import_fields; static import_fields csv_fields_outlook[] = { {"Title", NOMAP}, {"First Name", E_CONTACT_GIVEN_NAME}, {"Middle Name", NOMAP}, {"Last Name", E_CONTACT_FAMILY_NAME}, {"Suffix", NOMAP}, {"Company", E_CONTACT_ORG}, {"Department", E_CONTACT_ORG_UNIT}, {"Job Title", E_CONTACT_TITLE}, {"Business Street", NOMAP, FLAG_WORK_ADDRESS|FLAG_STREET }, {"Business Street 2", NOMAP, FLAG_WORK_ADDRESS|FLAG_STREET }, {"Business Street 3", NOMAP, FLAG_WORK_ADDRESS|FLAG_STREET}, {"Business City", NOMAP, FLAG_WORK_ADDRESS|FLAG_CITY}, {"Business State", NOMAP, FLAG_WORK_ADDRESS|FLAG_STATE}, {"Business Postal Code", NOMAP, FLAG_WORK_ADDRESS|FLAG_POSTAL_CODE}, {"Business Country", NOMAP, FLAG_WORK_ADDRESS|FLAG_COUNTRY}, {"Home Street", NOMAP, FLAG_HOME_ADDRESS|FLAG_STREET}, {"Home Street 2", NOMAP, FLAG_HOME_ADDRESS|FLAG_STREET}, {"Home Street 3", NOMAP, FLAG_HOME_ADDRESS|FLAG_STREET}, {"Home City", NOMAP, FLAG_HOME_ADDRESS|FLAG_CITY}, {"Home State", NOMAP, FLAG_HOME_ADDRESS|FLAG_STATE}, {"Home Postal Code", NOMAP,FLAG_HOME_ADDRESS|FLAG_POSTAL_CODE}, {"Home Country", NOMAP, FLAG_HOME_ADDRESS|FLAG_COUNTRY}, {"Other Street", NOMAP, FLAG_OTHER_ADDRESS|FLAG_STREET}, {"Other Street 2", NOMAP, FLAG_OTHER_ADDRESS|FLAG_STREET}, {"Other Street 3", NOMAP, FLAG_OTHER_ADDRESS|FLAG_STREET}, {"Other City", NOMAP, FLAG_OTHER_ADDRESS|FLAG_CITY}, {"Other State", NOMAP, FLAG_OTHER_ADDRESS|FLAG_STATE}, {"Other Postal Code", NOMAP, FLAG_OTHER_ADDRESS|FLAG_POSTAL_CODE}, {"Other Country", NOMAP, FLAG_OTHER_ADDRESS|FLAG_COUNTRY}, {"Assistant's Phone", E_CONTACT_PHONE_ASSISTANT}, {"Business Fax", E_CONTACT_PHONE_BUSINESS_FAX}, {"Business Phone", E_CONTACT_PHONE_BUSINESS}, {"Business Phone 2", E_CONTACT_PHONE_BUSINESS_2}, {"Callback", E_CONTACT_PHONE_CALLBACK}, {"Car Phone", E_CONTACT_PHONE_CAR}, {"Company Main Phone", E_CONTACT_PHONE_COMPANY}, {"Home Fax", E_CONTACT_PHONE_HOME_FAX}, {"Home Phone", E_CONTACT_PHONE_HOME}, {"Home Phone 2", E_CONTACT_PHONE_HOME_2}, {"ISDN", E_CONTACT_PHONE_ISDN}, {"Mobile Phone", E_CONTACT_PHONE_MOBILE}, {"Other Fax", E_CONTACT_PHONE_OTHER_FAX}, {"Other Phone", E_CONTACT_PHONE_OTHER}, {"Pager", E_CONTACT_PHONE_PAGER}, {"Primary Phone", E_CONTACT_PHONE_PRIMARY}, {"Radio Phone", E_CONTACT_PHONE_RADIO}, {"TTY/TDD Phone", E_CONTACT_PHONE_TTYTDD}, {"Telex", E_CONTACT_PHONE_TELEX}, {"Account", NOMAP}, {"Anniversary", NOMAP, FLAG_DATE_ANNIVERSARY}, {"Assistant's Name", E_CONTACT_ASSISTANT}, {"Billing Information", NOMAP}, {"Birthday", NOMAP, FLAG_DATE_BDAY}, {"Business Address PO Box", NOMAP, FLAG_WORK_ADDRESS|FLAG_POBOX}, {"Categories", E_CONTACT_CATEGORIES}, {"Children", NOMAP}, {"Directory Server", NOMAP}, {"E-mail Address", E_CONTACT_EMAIL_1}, {"E-mail Type", NOMAP}, {"E-mail Display Name", NOMAP}, {"E-mail 2 Address", E_CONTACT_EMAIL_2}, {"E-mail 2 Type", NOMAP}, {"E-mail 2 Display Name", NOMAP}, {"E-mail 3 Address", E_CONTACT_EMAIL_3}, {"E-mail 3 Type", NOMAP}, {"E-mail 3 Display Name", NOMAP}, {"Gender", NOMAP}, {"Government ID Number", NOMAP}, {"Hobby", NOMAP}, {"Home Address PO Box", NOMAP, FLAG_HOME_ADDRESS|FLAG_POBOX}, {"Initials", NOMAP}, {"Internet FREE/BUSY", E_CONTACT_FREEBUSY_URL}, {"Keywords", NOMAP}, {"Language", NOMAP}, {"Location", NOMAP}, {"Managers Name", E_CONTACT_MANAGER}, {"Mileage", NOMAP}, {"Notes", NOMAP}, {"Office Location", NOMAP}, {"Organizational ID Number", NOMAP}, {"Other Address PO Box", NOMAP, FLAG_OTHER_ADDRESS|FLAG_POBOX}, {"Priority", NOMAP}, {"Private", NOMAP}, {"Profession", NOMAP}, {"Referred By", NOMAP}, {"Senstivity", NOMAP}, {"Spouse", E_CONTACT_SPOUSE}, {"User 1", NOMAP}, {"User 2", NOMAP}, {"User 3", NOMAP}, {"User 4", NOMAP}, {"Web Page", E_CONTACT_HOMEPAGE_URL}, }; static import_fields csv_fields_mozilla[] = { {"First Name", E_CONTACT_GIVEN_NAME}, {"Last Name", E_CONTACT_FAMILY_NAME}, {"Display Name", NOMAP}, {"NickName", E_CONTACT_NICKNAME}, {"E-mail Address", E_CONTACT_EMAIL_1}, {"E-mail 2 Address", E_CONTACT_EMAIL_2}, {"Business Phone", E_CONTACT_PHONE_BUSINESS}, {"Home Phone", E_CONTACT_PHONE_HOME}, {"Business Fax", E_CONTACT_PHONE_BUSINESS_FAX}, {"Pager", E_CONTACT_PHONE_PAGER}, {"Mobile Phone", E_CONTACT_PHONE_MOBILE}, {"Home Street", NOMAP, FLAG_HOME_ADDRESS|FLAG_STREET}, {"Home Street 2", NOMAP, FLAG_HOME_ADDRESS|FLAG_STREET}, {"Home City", NOMAP, FLAG_HOME_ADDRESS|FLAG_CITY}, {"Home State", NOMAP, FLAG_HOME_ADDRESS|FLAG_STATE}, {"Home Postal Code", NOMAP,FLAG_HOME_ADDRESS|FLAG_POSTAL_CODE}, {"Home Country", NOMAP, FLAG_HOME_ADDRESS|FLAG_COUNTRY}, {"Business Street", NOMAP, FLAG_WORK_ADDRESS|FLAG_STREET }, {"Business Street 2", NOMAP, FLAG_WORK_ADDRESS|FLAG_STREET }, {"Business City", NOMAP, FLAG_WORK_ADDRESS|FLAG_CITY}, {"Business State", NOMAP, FLAG_WORK_ADDRESS|FLAG_STATE}, {"Business Postal Code", NOMAP, FLAG_WORK_ADDRESS|FLAG_POSTAL_CODE}, {"Business Country", NOMAP, FLAG_WORK_ADDRESS|FLAG_COUNTRY}, {"Job Title", E_CONTACT_TITLE}, {"Department", E_CONTACT_ORG_UNIT}, {"Company", E_CONTACT_ORG}, {"Web Page", E_CONTACT_HOMEPAGE_URL}, {"Home Web Page", NOMAP}, {"Birth Year", NOMAP, FLAG_BIRTH_YEAR}, {"Birth Month", NOMAP,FLAG_BIRTH_MONTH}, {"Birth Day", NOMAP, FLAG_BIRTH_DAY}, {"Custom 1", NOMAP}, {"Custom 2", NOMAP}, {"Custom 3", NOMAP}, {"Custom 4", NOMAP}, {"Notes", NOMAP}, }; static import_fields csv_fields_evolution[] = { {"First Name", E_CONTACT_GIVEN_NAME}, {"Last Name", E_CONTACT_FAMILY_NAME}, {"id", NOMAP, FLAG_INVALID}, {"NickName", E_CONTACT_NICKNAME}, {"E-mail Address", E_CONTACT_EMAIL_1}, {"E-mail 2 Address", E_CONTACT_EMAIL_2}, {"E-mail 3 Address", E_CONTACT_EMAIL_3}, {"E-mail 4 Address", E_CONTACT_EMAIL_4}, {"Wants HTML", E_CONTACT_WANTS_HTML}, {"Business Phone", E_CONTACT_PHONE_BUSINESS}, {"Home Phone", E_CONTACT_PHONE_HOME}, {"Business Fax", E_CONTACT_PHONE_BUSINESS_FAX}, {"Pager", E_CONTACT_PHONE_PAGER}, {"Mobile Phone", E_CONTACT_PHONE_MOBILE}, {"Home Street", NOMAP, FLAG_HOME_ADDRESS|FLAG_STREET}, {"Home Street 2", NOMAP, FLAG_INVALID}, {"Home City", NOMAP, FLAG_HOME_ADDRESS|FLAG_CITY}, {"Home State", NOMAP, FLAG_HOME_ADDRESS|FLAG_STATE}, {"Home Postal Code", NOMAP,FLAG_HOME_ADDRESS|FLAG_POSTAL_CODE}, {"Home Country", NOMAP, FLAG_HOME_ADDRESS|FLAG_COUNTRY}, {"Business Street", NOMAP, FLAG_WORK_ADDRESS|FLAG_STREET }, {"Business Street 2", NOMAP, FLAG_INVALID }, {"Business City", NOMAP, FLAG_WORK_ADDRESS|FLAG_CITY}, {"Business State", NOMAP, FLAG_WORK_ADDRESS|FLAG_STATE}, {"Business Postal Code", NOMAP, FLAG_WORK_ADDRESS|FLAG_POSTAL_CODE}, {"Business Country", NOMAP, FLAG_WORK_ADDRESS|FLAG_COUNTRY}, {"Job Title", E_CONTACT_TITLE}, {"Office", E_CONTACT_OFFICE}, {"Company", E_CONTACT_ORG}, {"Web Page", E_CONTACT_HOMEPAGE_URL}, {"Cal uri", E_CONTACT_CALENDAR_URI}, {"Birth Year", NOMAP, FLAG_BIRTH_YEAR}, {"Birth Month", NOMAP,FLAG_BIRTH_MONTH}, {"Birth Day", NOMAP, FLAG_BIRTH_DAY}, {"Notes", E_CONTACT_NOTE}, }; static void add_to_notes(EContact *contact, gint i, gchar *val) { const gchar *old_text; const gchar *field_text = NULL; GString *new_text; old_text = e_contact_get_const(contact, E_CONTACT_NOTE); if (importer == OUTLOOK_IMPORTER) { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_outlook)) field_text = csv_fields_outlook[i].csv_attribute; } else if (importer == MOZILLA_IMPORTER) { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_mozilla)) field_text = csv_fields_mozilla[i].csv_attribute; } else { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_evolution)) field_text = csv_fields_evolution[i].csv_attribute; } if (!field_text) return; new_text = g_string_new(old_text); if (strlen(new_text->str) != 0) new_text = g_string_append_c(new_text, '\n'); new_text = g_string_append(new_text, field_text); new_text = g_string_append_c(new_text, ':'); new_text = g_string_append(new_text, val); e_contact_set(contact, E_CONTACT_NOTE, new_text->str); g_string_free(new_text, TRUE); } /* @str: a date string in the format MM-DD-YYYY or MMDDYYYY */ static EContactDate* date_from_string (const gchar *str) { EContactDate* date; gint i = 0; g_return_val_if_fail (str != NULL, NULL); date = e_contact_date_new(); if (g_ascii_isdigit (str[i]) && g_ascii_isdigit (str[i+1])) { date->month = str[i] * 10 + str[i+1] - '0' * 11; i = i+3; } else { date->month = str[i] - '0' * 1; i = i+2; } if (g_ascii_isdigit (str[i]) && g_ascii_isdigit (str[i+1])) { date->day = str[i] * 10 + str[i+1] - '0' * 11; i = i+3; } else { date->day = str[i] - '0' * 1; i = i+2; } date->year = str[i] * 1000 + str[i+1] * 100 + str[i+2] * 10 + str[i+3] - '0' * 1111; return date; } static gboolean parseLine (CSVImporter *gci, EContact *contact, gchar *buf) { gchar *ptr = buf, *do_free = NULL; GString *value; gint i = 0; gint flags = 0; gint contact_field; EContactAddress *home_address = NULL, *work_address = NULL, *other_address = NULL; EContactDate *bday = NULL; GString *home_street, *work_street, *other_street; home_street = g_string_new(""); work_street = g_string_new(""); other_street = g_string_new(""); home_address = g_new0(EContactAddress, 1); work_address = g_new0(EContactAddress, 1); other_address = g_new0(EContactAddress, 1); bday = g_new0(EContactDate, 1); if (!g_utf8_validate (ptr, -1, NULL)) { do_free = g_convert (ptr, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL); ptr = do_free; } while (*ptr != '\n') { value = g_string_new(""); while (*ptr != delimiter) { if (*ptr == '\n') break; if (*ptr != '"') { g_string_append_unichar (value, g_utf8_get_char (ptr)); } else { ptr = g_utf8_next_char (ptr); while (*ptr && *ptr != '"') { g_string_append_unichar (value, g_utf8_get_char (ptr)); ptr = g_utf8_next_char (ptr); } if (!*ptr) break; } ptr = g_utf8_next_char (ptr); } contact_field = NOMAP; flags = FLAG_INVALID; if (importer == OUTLOOK_IMPORTER) { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_outlook)) { contact_field = csv_fields_outlook[i].contact_field; flags = csv_fields_outlook[i].flags; } } else if (importer == MOZILLA_IMPORTER) { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_mozilla)) { contact_field = csv_fields_mozilla[i].contact_field; flags = csv_fields_mozilla[i].flags; } } else { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_evolution)) { contact_field = csv_fields_evolution[i].contact_field; flags = csv_fields_evolution[i].flags; } } if (strlen(value->str) != 0) { if (contact_field != NOMAP) { if (importer == OUTLOOK_IMPORTER) { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_outlook)) e_contact_set (contact, csv_fields_outlook[i].contact_field, value->str); } else if (importer == MOZILLA_IMPORTER) { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_mozilla)) e_contact_set (contact, csv_fields_mozilla[i].contact_field, value->str); } else { if (i >= 0 && i < G_N_ELEMENTS (csv_fields_evolution)) { if (csv_fields_evolution[i].contact_field == E_CONTACT_WANTS_HTML) e_contact_set (contact, csv_fields_evolution[i].contact_field, GINT_TO_POINTER (g_ascii_strcasecmp (value->str, "TRUE") == 0)); else e_contact_set (contact, csv_fields_evolution[i].contact_field, value->str); } } } else { switch (flags) { case FLAG_HOME_ADDRESS|FLAG_STREET: if (strlen(home_street->str) != 0) { home_street = g_string_append(home_street, ",\n"); } home_street = g_string_append(home_street, value->str); break; case FLAG_HOME_ADDRESS|FLAG_CITY: home_address->locality = g_strdup(value->str); break; case FLAG_HOME_ADDRESS|FLAG_STATE: home_address->region = g_strdup(value->str); break; case FLAG_HOME_ADDRESS|FLAG_POSTAL_CODE: home_address->code = g_strdup(value->str); break; case FLAG_HOME_ADDRESS|FLAG_POBOX: home_address->po = g_strdup(value->str); break; case FLAG_HOME_ADDRESS|FLAG_COUNTRY: home_address->country = g_strdup(value->str); break; case FLAG_WORK_ADDRESS|FLAG_STREET: if (strlen(work_street->str) != 0) { work_street = g_string_append(work_street, ",\n"); } work_street = g_string_append(work_street, value->str); break; case FLAG_WORK_ADDRESS|FLAG_CITY: work_address->locality = g_strdup(value->str); break; case FLAG_WORK_ADDRESS|FLAG_STATE: work_address->region = g_strdup(value->str); break; case FLAG_WORK_ADDRESS|FLAG_POSTAL_CODE: work_address->code = g_strdup(value->str); break; case FLAG_WORK_ADDRESS|FLAG_POBOX: work_address->po = g_strdup(value->str); break; case FLAG_WORK_ADDRESS|FLAG_COUNTRY: work_address->country = g_strdup(value->str); break; case FLAG_OTHER_ADDRESS|FLAG_STREET: if (strlen(other_street->str) != 0) { other_street = g_string_append(other_street, ",\n"); } other_street = g_string_append(other_street, value->str); break; case FLAG_OTHER_ADDRESS|FLAG_CITY: other_address->locality = g_strdup(value->str); break; case FLAG_OTHER_ADDRESS|FLAG_STATE: other_address->region = g_strdup(value->str); break; case FLAG_OTHER_ADDRESS|FLAG_POSTAL_CODE: other_address->code = g_strdup(value->str); break; case FLAG_OTHER_ADDRESS|FLAG_POBOX: other_address->po = g_strdup(value->str); break; case FLAG_OTHER_ADDRESS|FLAG_COUNTRY: other_address->country = g_strdup(value->str); break; case FLAG_DATE_BDAY: e_contact_set(contact, E_CONTACT_BIRTH_DATE, date_from_string(value->str)); break; case FLAG_DATE_ANNIVERSARY: e_contact_set(contact, E_CONTACT_ANNIVERSARY, date_from_string(value->str)); break; case FLAG_BIRTH_DAY: bday->day = atoi(value->str); break; case FLAG_BIRTH_YEAR: bday->year = atoi(value->str); break; case FLAG_BIRTH_MONTH: bday->month = atoi(value->str); break; case FLAG_INVALID: break; default: add_to_notes(contact, i, value->str); } } } i++; g_string_free(value, TRUE); if (*ptr != '\n') ptr = g_utf8_next_char (ptr); } if (strlen(home_street->str) != 0) home_address->street = g_strdup(home_street->str); if (strlen(work_street->str) != 0) work_address->street = g_strdup(work_street->str); if (strlen(other_street->str) != 0) other_address->street = g_strdup(other_street->str); g_string_free(home_street, TRUE); g_string_free(work_street, TRUE); g_string_free(other_street, TRUE); if (home_address->locality || home_address->country || home_address->code || home_address->region || home_address->street) e_contact_set (contact, E_CONTACT_ADDRESS_HOME, home_address); if (work_address->locality || work_address->country || work_address->code || work_address->region || work_address->street) e_contact_set (contact, E_CONTACT_ADDRESS_WORK, work_address); if (other_address->locality || other_address->country || other_address->code || other_address->region || other_address->street) e_contact_set (contact, E_CONTACT_ADDRESS_OTHER, other_address); if (importer != OUTLOOK_IMPORTER) { if (bday->day || bday->year || bday->month) e_contact_set(contact, E_CONTACT_BIRTH_DATE, bday); } g_free (do_free); return TRUE; } static EContact * getNextCSVEntry(CSVImporter *gci, FILE *f) { EContact *contact = NULL; GString *line; GString *str; gchar *buf; gchar c; /* if (!fgets(line, sizeof(line),f)) return NULL; if (gci->count == 0 && importer != MOZILLA_IMPORTER) { if (!fgets(line, sizeof(line),f)) return NULL; gci->count ++; } */ line = g_string_new(""); while (1) { c = fgetc (f); if (c == EOF) return NULL; if (c == '\n') { g_string_append_c (line, c); break; } if (c == '"') { g_string_append_c (line, c); c = fgetc (f); while (!feof (f) && c != '"') { g_string_append_c (line, c); c = fgetc (f); } g_string_append_c (line, c); } else g_string_append_c (line, c); } if (gci->count == 0 && importer != MOZILLA_IMPORTER) { g_string_free (line, TRUE); line = g_string_new(""); while (1) { c = fgetc (f); if (c == EOF) return NULL; if (c == '\n') { g_string_append_c (line, c); break; } if (c == '"') { g_string_append_c (line, c); c = fgetc (f); while (!feof (f) && c != '"') { g_string_append_c (line, c); c = fgetc (f); } g_string_append_c (line, c); } else g_string_append_c (line, c); } gci->count ++; } str = g_string_new(""); str = g_string_append (str, line->str); g_string_free (line, TRUE); if (strlen(str->str) == 0) { g_string_free(str, TRUE); return NULL; } contact = e_contact_new(); buf = str->str; if (!parseLine (gci, contact, buf)) { g_object_unref(contact); return NULL; } gci->count++; g_string_free(str, TRUE); return contact; } static gboolean csv_import_contacts(gpointer d) { CSVImporter *gci = d; EContact *contact = NULL; while ((contact = getNextCSVEntry(gci, gci->file))) { e_book_add_contact(gci->book, contact, NULL); gci->contacts = g_slist_prepend(gci->contacts, contact); } if (contact == NULL) { gci->state = 1; } if (gci->state == 1) { csv_import_done(gci); return FALSE; } else { e_import_status ( gci->import, gci->target, _("Importing..."), ftell (gci->file) * 100 / gci->size); return TRUE; } } static void primary_selection_changed_cb (ESourceSelector *selector, EImportTarget *target) { g_datalist_set_data_full(&target->data, "csv-source", g_object_ref(e_source_selector_peek_primary_selection(selector)), g_object_unref); } static GtkWidget * csv_getwidget(EImport *ei, EImportTarget *target, EImportImporter *im) { GtkWidget *vbox, *selector; ESource *primary; ESourceList *source_list; /* FIXME Better error handling */ if (!e_book_get_addressbooks (&source_list, NULL)) return NULL; vbox = gtk_vbox_new (FALSE, FALSE); selector = e_source_selector_new (source_list); e_source_selector_show_selection (E_SOURCE_SELECTOR (selector), FALSE); gtk_box_pack_start (GTK_BOX (vbox), selector, FALSE, TRUE, 6); primary = g_datalist_get_data(&target->data, "csv-source"); if (primary == NULL) { primary = e_source_list_peek_source_any (source_list); g_object_ref(primary); g_datalist_set_data_full(&target->data, "csv-source", primary, g_object_unref); } e_source_selector_set_primary_selection (E_SOURCE_SELECTOR (selector), primary); g_object_unref (source_list); g_signal_connect ( selector, "primary_selection_changed", G_CALLBACK (primary_selection_changed_cb), target); gtk_widget_show_all (vbox); return vbox; } static const gchar *supported_extensions[4] = { ".csv", ".tab" , ".txt", NULL }; static gboolean csv_supported(EImport *ei, EImportTarget *target, EImportImporter *im) { gchar *ext; gint i; EImportTargetURI *s; if (target->type != E_IMPORT_TARGET_URI) return FALSE; s = (EImportTargetURI *)target; if (s->uri_src == NULL) return TRUE; if (strncmp(s->uri_src, "file:///", 8) != 0) return FALSE; ext = strrchr(s->uri_src, '.'); if (ext == NULL) return FALSE; for (i = 0; supported_extensions[i] != NULL; i++) { if (g_ascii_strcasecmp(supported_extensions[i], ext) == 0) { if (i == 0) { delimiter = CSV_FILE_DELIMITER; } else { delimiter = TAB_FILE_DELIMITER; } return TRUE; } } return FALSE; } static void csv_import_done(CSVImporter *gci) { if (gci->idle_id) g_source_remove(gci->idle_id); fclose (gci->file); g_object_unref(gci->book); g_slist_foreach(gci->contacts, (GFunc) g_object_unref, NULL); g_slist_free(gci->contacts); e_import_complete(gci->import, gci->target); g_object_unref(gci->import); g_free (gci); } static void csv_import (EImport *ei, EImportTarget *target, EImportImporter *im) { CSVImporter *gci; EBook *book; gchar *filename; FILE *file; EImportTargetURI *s = (EImportTargetURI *) target; filename = g_filename_from_uri (s->uri_src, NULL, NULL); if (filename == NULL) { g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src); return; } book = e_book_new(g_datalist_get_data(&target->data, "csv-source"), NULL); if (book == NULL) { g_message("Couldn't Create EBook"); e_import_complete(ei, target); g_free (filename); return; } file = g_fopen (filename, "r"); g_free (filename); if (file == NULL) { g_message("Can't open .csv file"); e_import_complete(ei, target); g_object_unref(book); return; } gci = g_malloc0(sizeof(*gci)); g_datalist_set_data(&target->data, "csv-data", gci); gci->import = g_object_ref(ei); gci->target = target; gci->book = book; gci->file = file; gci->count = 0; fseek(file, 0, SEEK_END); gci->size = ftell(file); fseek(file, 0, SEEK_SET); e_book_open(gci->book, FALSE, NULL); gci->idle_id = g_idle_add (csv_import_contacts, gci); } static void outlook_csv_import(EImport *ei, EImportTarget *target, EImportImporter *im) { importer = OUTLOOK_IMPORTER; csv_import(ei, target, im); } static void mozilla_csv_import(EImport *ei, EImportTarget *target, EImportImporter *im) { importer = MOZILLA_IMPORTER; csv_import(ei, target, im); } static void evolution_csv_import(EImport *ei, EImportTarget *target, EImportImporter *im) { importer = EVOLUTION_IMPORTER; csv_import(ei, target, im); } static void csv_cancel(EImport *ei, EImportTarget *target, EImportImporter *im) { CSVImporter *gci = g_datalist_get_data(&target->data, "csv-data"); if (gci) gci->state = 1; } static GtkWidget * csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) { GtkWidget *preview; GList *contacts = NULL; EContact *contact; EImportTargetURI *s = (EImportTargetURI *)target; gchar *filename; FILE *file; CSVImporter *gci; filename = g_filename_from_uri (s->uri_src, NULL, NULL); if (filename == NULL) { g_message (G_STRLOC ": Couldn't get filename from URI '%s'", s->uri_src); return NULL; } file = g_fopen (filename, "r"); g_free (filename); if (file == NULL) { g_message (G_STRLOC ": Can't open .csv file"); return NULL; } gci = g_malloc0 (sizeof (*gci)); gci->file = file; gci->count = 0; fseek(file, 0, SEEK_END); gci->size = ftell (file); fseek (file, 0, SEEK_SET); while (contact = getNextCSVEntry (gci, gci->file), contact != NULL) { contacts = g_list_prepend (contacts, contact); } contacts = g_list_reverse (contacts); preview = evolution_contact_importer_get_preview_widget (contacts); g_list_foreach (contacts, (GFunc) g_object_unref, NULL); g_list_free (contacts); fclose (file); g_free (gci); return preview; } static GtkWidget * outlook_csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) { importer = OUTLOOK_IMPORTER; return csv_get_preview (ei, target, im); } static GtkWidget * mozilla_csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) { importer = MOZILLA_IMPORTER; return csv_get_preview (ei, target, im); } static GtkWidget * evolution_csv_get_preview (EImport *ei, EImportTarget *target, EImportImporter *im) { importer = EVOLUTION_IMPORTER; return csv_get_preview (ei, target, im); } static EImportImporter csv_outlook_importer = { E_IMPORT_TARGET_URI, 0, csv_supported, csv_getwidget, outlook_csv_import, csv_cancel, outlook_csv_get_preview, }; static EImportImporter csv_mozilla_importer = { E_IMPORT_TARGET_URI, 0, csv_supported, csv_getwidget, mozilla_csv_import, csv_cancel, mozilla_csv_get_preview, }; static EImportImporter csv_evolution_importer = { E_IMPORT_TARGET_URI, 0, csv_supported, csv_getwidget, evolution_csv_import, csv_cancel, evolution_csv_get_preview, }; EImportImporter * evolution_csv_outlook_importer_peek(void) { csv_outlook_importer.name = _("Outlook CSV or Tab (.csv, .tab)"); csv_outlook_importer.description = _("Outlook CSV and Tab Importer"); return &csv_outlook_importer; } EImportImporter * evolution_csv_mozilla_importer_peek(void) { csv_mozilla_importer.name = _("Mozilla CSV or Tab (.csv, .tab)"); csv_mozilla_importer.description = _("Mozilla CSV and Tab Importer"); return &csv_mozilla_importer; } EImportImporter * evolution_csv_evolution_importer_peek(void) { csv_evolution_importer.name = _("Evolution CSV or Tab (.csv, .tab)"); csv_evolution_importer.description = _("Evolution CSV and Tab Importer"); return &csv_evolution_importer; }