5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
16 #include <sys/types.h>
17 #include "abook_curses.h"
30 extern abook_field_list *fields_list;
31 extern int fields_count;
34 * function declarations
38 * import filter prototypes
41 static int ldif_parse_file(FILE *handle);
42 static int mutt_parse_file(FILE *in);
43 static int pine_parse_file(FILE *in);
44 static int csv_parse_file(FILE *in);
45 static int allcsv_parse_file(FILE *in);
46 static int palmcsv_parse_file(FILE *in);
47 static int vcard_parse_file(FILE *in);
50 * export filter prototypes
53 static int ldif_export_database(FILE *out, struct db_enumerator e);
54 static int html_export_database(FILE *out, struct db_enumerator e);
55 static int pine_export_database(FILE *out, struct db_enumerator e);
56 static int csv_export_database(FILE *out, struct db_enumerator e);
57 static int allcsv_export_database(FILE *out, struct db_enumerator e);
58 static int palm_export_database(FILE *out, struct db_enumerator e);
59 static int gcrd_export_database(FILE *out, struct db_enumerator e);
60 static int mutt_alias_export(FILE *out, struct db_enumerator e);
61 static int elm_alias_export(FILE *out, struct db_enumerator e);
62 static int text_export_database(FILE *out, struct db_enumerator e);
63 static int spruce_export_database(FILE *out, struct db_enumerator e);
64 static int wl_export_database(FILE *out, struct db_enumerator e);
65 static int bsdcal_export_database(FILE *out, struct db_enumerator e);
68 * end of function declarations
71 struct abook_input_filter i_filters[] = {
72 { "abook", N_("abook native format"), parse_database },
73 { "ldif", N_("ldif / Netscape addressbook"), ldif_parse_file },
74 { "mutt", N_("mutt alias"), mutt_parse_file },
75 { "pine", N_("pine addressbook"), pine_parse_file },
76 { "csv", N_("comma separated values"), csv_parse_file },
77 { "allcsv", N_("comma separated values (all fields)"), allcsv_parse_file },
78 { "palmcsv", N_("Palm comma separated values"), palmcsv_parse_file },
79 { "vcard", N_("vCard file"), vcard_parse_file },
83 struct abook_output_filter e_filters[] = {
84 { "abook", N_("abook native format"), write_database },
85 { "ldif", N_("ldif / Netscape addressbook (.4ld)"), ldif_export_database },
86 { "mutt", N_("mutt alias"), mutt_alias_export },
87 { "html", N_("html document"), html_export_database },
88 { "pine", N_("pine addressbook"), pine_export_database },
89 { "gcrd", N_("GnomeCard (VCard) addressbook"), gcrd_export_database },
90 { "csv", N_("comma separated values"), csv_export_database },
91 { "allcsv", N_("comma separated values (all fields)"), allcsv_export_database },
92 { "palmcsv", N_("Palm comma separated values"), palm_export_database},
93 { "elm", N_("elm alias"), elm_alias_export },
94 { "text", N_("plain text"), text_export_database },
95 { "wl", N_("Wanderlust address book"), wl_export_database },
96 { "spruce", N_("Spruce address book"), spruce_export_database },
97 { "bsdcal", N_("BSD calendar"), bsdcal_export_database },
111 for(i=0; *i_filters[i].filtname ; i++)
112 printf("\t%s\t%s\n", i_filters[i].filtname,
113 gettext(i_filters[i].desc));
118 for(i=0; *e_filters[i].filtname ; i++)
119 printf("\t%s\t%s\n", e_filters[i].filtname,
120 gettext(e_filters[i].desc));
126 number_of_output_filters()
130 for(i=0; *e_filters[i].filtname ; i++)
137 number_of_input_filters()
141 for(i=0; *i_filters[i].filtname ; i++)
150 char *username = getenv("USER");
151 struct passwd *pwent;
155 pwent = getpwnam(username);
157 if((tmp = xstrdup(pwent->pw_gecos)) == NULL)
158 return xstrdup(username);
160 rtn = sscanf(pwent->pw_gecos, "%[^,]", tmp);
161 if (rtn == EOF || rtn == 0) {
163 return xstrdup(username);
172 static int i_read_file(char *filename, int (*func) (FILE *in));
181 refresh_statusline();
182 headerline(_("import database"));
184 mvaddstr(3, 1, _("please select a filter"));
187 for(i=0; *i_filters[i].filtname ; i++)
188 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
189 i_filters[i].filtname,
190 gettext(i_filters[i].desc));
192 mvprintw(6 + i, 6, _("x -\tcancel"));
200 int tmp = db_n_items();
204 filter = getch() - 'a';
205 if(filter == 'x' - 'a' ||
206 filter >= number_of_input_filters() || filter < 0) {
211 mvaddstr(5+filter, 2, "->");
213 filename = ask_filename(_("Filename: "));
219 if(i_read_file(filename, i_filters[filter].func ))
220 statusline_msg(_("Error occured while opening the file"));
221 else if(tmp == db_n_items())
222 statusline_msg(_("File does not seem to be a valid addressbook"));
233 i_read_file(char *filename, int (*func) (FILE *in))
238 if( (in = abook_fopen( filename, "r" )) == NULL )
249 import_file(char filtname[FILTNAME_LEN], char *filename)
252 int tmp = db_n_items();
256 if(! strncasecmp(i_filters[i].filtname, filtname,
259 if(! *i_filters[i].filtname) {
268 if(!strcmp(filename, "-")) {
270 if((fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode))
273 ret = (*i_filters[i].func) (stdin);
275 ret = i_read_file(filename, i_filters[i].func);
277 if(tmp == db_n_items())
287 static int e_write_file(char *filename,
288 int (*func) (FILE *in, struct db_enumerator e), int mode);
298 refresh_statusline();
299 headerline(_("export database"));
301 mvaddstr(3, 1, _("please select a filter"));
304 for(i = 0; *e_filters[i].filtname ; i++)
305 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
306 e_filters[i].filtname,
307 gettext(e_filters[i].desc));
309 mvprintw(6 + i, 6, _("x -\tcancel"));
316 int enum_mode = ENUM_ALL;
321 filter = getch() - 'a';
322 if(filter == 'x' - 'a' ||
323 filter >= number_of_output_filters() || filter < 0) {
328 mvaddstr(5 + filter, 2, "->");
330 if(selected_items()) {
331 switch(statusline_askchoice(
332 _("Export <a>ll, export <s>elected, or <c>ancel?"),
333 S_("keybindings:all/selected/cancel|asc"), 3)) {
337 enum_mode = ENUM_SELECTED;
347 filename = ask_filename(_("Filename: "));
353 if( e_write_file(filename, e_filters[filter].func, enum_mode))
354 statusline_msg(_("Error occured while exporting"));
363 e_write_file(char *filename, int (*func) (FILE *in, struct db_enumerator e),
368 struct db_enumerator enumerator = init_db_enumerator(mode);
370 if((out = fopen(filename, "a")) == NULL)
376 ret = (*func) (out, enumerator);
384 fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode)
387 struct db_enumerator e = init_db_enumerator(enum_mode);
390 if(!strncasecmp(e_filters[i].filtname, filtname,
393 if(!*e_filters[i].filtname) {
399 return (e_filters[i].func) (handle, e);
405 export_file(char filtname[FILTNAME_LEN], char *filename)
407 const int mode = ENUM_ALL;
410 struct db_enumerator e = init_db_enumerator(mode);
413 if(!strncasecmp(e_filters[i].filtname, filtname,
416 if(!*e_filters[i].filtname) {
425 if(!strcmp(filename, "-"))
426 ret = (e_filters[i].func) (stdout, e);
428 ret = e_write_file(filename, e_filters[i].func, mode);
434 * end of common functions
443 static void ldif_fix_string(char *str);
445 #define LDIF_ITEM_FIELDS 16
447 typedef char *ldif_item[LDIF_ITEM_FIELDS];
449 static ldif_item ldif_field_names = {
461 "facsimiletelephonenumber",
465 "objectclass", /* this must be the last entry */
468 static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
471 ADDRESS, /* "streetaddress" */
472 ADDRESS2, /* "streetaddress2" */
473 CITY, /* "locality" */
475 ZIP, /* "postalcode" */
476 COUNTRY, /* "countryname" */
477 PHONE, /* "homephone" */
478 NOTES, /* "description" */
480 FAX, /* "facsimiletelephonenumber" */
481 MOBILEPHONE, /* "cellphone" */
482 WORKPHONE, /* "xmozillaanyphone" */
483 NICK, /* "xmozillanickname" */
484 -1, /* "objectclass" */ /* this must be the last entry */
489 ldif_read_line(FILE *in)
502 if(feof(in) || !line)
511 fseek(in, pos, SEEK_SET); /* fixme ! */
521 buf = strconcat(buf, ptr, NULL);
526 if(buf && *buf == '#' ) {
535 ldif_add_item(ldif_item li)
540 item = item_create();
542 if(!li[LDIF_ITEM_FIELDS -1])
546 for(i=0; i < LDIF_ITEM_FIELDS; i++) {
547 if(ldif_conv_table[i] >= 0 && li[i] && *li[i])
548 item_fput(item,ldif_conv_table[i],xstrdup(li[i]));
551 add_item2database(item);
554 for(i=0; i < LDIF_ITEM_FIELDS; i++)
561 ldif_convert(ldif_item item, char *type, char *value)
565 if(!strcmp(type, "dn")) {
570 for(i=0; i < LDIF_ITEM_FIELDS; i++) {
571 if(!safe_strcmp(ldif_field_names[i], type) && *value) {
572 if(i == LDIF_ITEM_FIELDS - 1) /* this is a dirty hack */
573 if(safe_strcmp("person", value))
576 if(item_fget(item, i))
577 free(item_fget(item, i));
579 item_fput(item, i, xstrdup(value));
585 ldif_parse_file(FILE *handle)
592 memset(item, 0, sizeof(item));
595 if( !(line = ldif_read_line(handle)) )
598 if(-1 == (str_parse_line(line, &type, &value, &vlen))) {
600 continue; /* just skip the errors */
603 ldif_fix_string(value);
605 ldif_convert(item, type, value);
608 } while ( !feof(handle) );
610 ldif_convert(item, "dn", "");
616 ldif_fix_string(char *str)
620 for(i = 0, j = 0; j < (int)strlen(str); i++, j++)
621 str[i] = ( str[j] == (char)0xc3 ?
622 (char) str[++j] + (char) 0x40 :
633 * mutt alias import filter
639 mutt_read_line(FILE *in, char **alias, char **rest)
641 char *line, *ptr, *tmp;
644 if( !(line = ptr = getaline(in)) )
645 return 1; /* error / EOF */
649 if(strncmp("alias", ptr, 5)) {
660 while( ! ISSPACE(*ptr) )
663 alias_len = (size_t)(ptr - tmp);
666 *alias = xmalloc_inc(alias_len, 1);
668 strncpy(*alias, tmp, alias_len);
669 *(*alias + alias_len) = 0;
673 *rest = xstrdup(ptr);
680 mutt_fix_quoting(char *p)
700 mutt_parse_email(list_item item)
702 char *line = item_fget(item, NAME);
710 mutt_fix_quoting(line);
711 tmp = strconcat("From: ", line, NULL);
712 getname(tmp, &name, &email);
716 item_fput(item, NAME, name);
721 item_fput(item, EMAIL, email);
726 * this is completely broken
729 while( (start = strchr(start, ',')) && i++ < MAX_EMAILS - 1) {
730 tmp = strconcat("From: ", ++start, NULL);
731 getname(tmp, &name, &email);
736 tmp = strconcat(item[EMAIL], ",", email, NULL);
748 mutt_parse_file(FILE *in)
750 list_item item = item_create();
753 memset(item, 0, fields_count * sizeof(char *));
755 if(!mutt_read_line(in,
756 (field_id(NICK) != -1) ?
757 &item[field_id(NICK)] : NULL,
758 &item[field_id(NAME)]))
759 mutt_parse_email(item);
766 add_item2database(item);
774 * end of mutt alias import filter
783 ldif_fput_type_and_value(FILE *out,char *type, char *value )
787 tmp = ldif_type_and_value(type, value, strlen(value));
795 ldif_export_database(FILE *out, struct db_enumerator e)
797 char email[MAX_EMAILSTR_LEN];
799 fprintf(out, "version: 1\n");
801 db_enumerate_items(e) {
804 get_first_email(email, e.item);
806 tmp = strdup_printf("cn=%s,mail=%s",db_name_get(e.item),email);
808 ldif_fput_type_and_value(out, "dn", tmp);
811 for(j = 0; j < LDIF_ITEM_FIELDS; j++) {
812 if(ldif_conv_table[j] >= 0) {
813 if(ldif_conv_table[j] == EMAIL)
814 ldif_fput_type_and_value(out,
815 ldif_field_names[j], email);
816 else if(db_fget(e.item,ldif_conv_table[j]))
817 ldif_fput_type_and_value(out,
820 ldif_conv_table[j]));
824 fprintf(out, "objectclass: top\n"
825 "objectclass: person\n\n");
832 * end of ldif export filter
839 static void html_export_write_head(FILE *out);
840 static void html_export_write_tail(FILE *out);
842 extern struct index_elem *index_elements;
845 html_print_emails(FILE *out, struct list_field *f)
847 abook_list *l = csv_to_abook_list(f->data);
849 for(; l; l = l->next) {
850 fprintf(out, "<a href=\"mailto:%s\">%s</a>", l->data, l->data);
859 html_export_database(FILE *out, struct db_enumerator e)
862 struct index_elem *cur;
869 html_export_write_head(out);
871 db_enumerate_items(e) {
872 fprintf(out, "<tr>");
873 for(cur = index_elements; cur; cur = cur->next) {
874 if(cur->type != INDEX_FIELD)
877 get_list_field(e.item, cur, &f);
879 if(f.type == FIELD_EMAILS) {
880 fprintf(out, "<td>");
881 html_print_emails(out, &f);
882 fprintf(out, "</td>");
885 fprintf(out, "<td>%s</td>", safe_str(f.data));
888 fprintf(out, "</tr>\n");
891 html_export_write_tail(out);
897 html_export_write_head(FILE *out)
899 char *realname = get_real_name(), *str;
900 struct index_elem *cur;
902 fprintf(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
903 fprintf(out, "<html>\n<head>\n <title>%s's addressbook</title>",
905 fprintf(out, "\n</head>\n<body>\n");
906 fprintf(out, "\n<h2>%s's addressbook</h2>\n", realname );
907 fprintf(out, "<br><br>\n\n");
909 fprintf(out, "<table border=\"1\" align=\"center\">\n<tr>");
910 for(cur = index_elements; cur; cur = cur->next) {
911 if(cur->type != INDEX_FIELD)
914 get_field_info(cur->d.field.id, NULL, &str, NULL);
915 fprintf(out, "<th>%s</th>", str);
917 fprintf(out, "</tr>\n\n");
923 html_export_write_tail(FILE *out)
925 fprintf(out, "\n</table>\n");
926 fprintf(out, "\n</body>\n</html>\n");
930 * end of html export filter
935 * pine addressbook import filter
938 #define PINE_BUF_SIZE 2048
941 pine_fixbuf(char *buf)
945 for(i = 0,j = 0; j < (int)strlen(buf); i++, j++)
946 buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
950 pine_convert_emails(char *s)
955 if(s == NULL || *s != '(')
958 for(i = 0; s[i]; i++)
961 if( ( tmp = strchr(s,')')) )
964 for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
965 if(i > MAX_LIST_ITEMS - 1) {
973 pine_parse_buf(char *buf)
978 char tmp[PINE_BUF_SIZE];
980 int pine_conv_table[]= {NICK, NAME, EMAIL, -1, NOTES};
982 item = item_create();
984 for(i=0, last=0; !last ; i++) {
985 if( !(end = strchr(start, '\t')) )
988 len = last ? strlen(start) : (int) (end-start);
989 len = min(len, PINE_BUF_SIZE - 1);
991 if(i < (int)(sizeof(pine_conv_table) / sizeof(*pine_conv_table))
992 && pine_conv_table[i] >= 0) {
993 strncpy(tmp, start, len);
996 item_fput(item, pine_conv_table[i],
1002 pine_convert_emails(item_fget(item, EMAIL));
1003 add_item2database(item);
1008 #define LINESIZE 1024
1011 pine_parse_file(FILE *in)
1013 char line[LINESIZE];
1018 fgets(line, LINESIZE, in);
1022 buf = xrealloc(buf, i*LINESIZE);
1025 fgets(line, LINESIZE, in);
1027 if(*ptr != ' ' || feof(in))
1041 pine_parse_buf(buf);
1050 * end of pine addressbook import filter
1055 * pine addressbook export filter
1057 * filter doesn't wrap the lines as it should but Pine seems to handle
1058 * created files without problems - JH
1062 pine_export_database(FILE *out, struct db_enumerator e)
1066 db_enumerate_items(e) {
1067 emails = db_email_get(e.item);
1068 fprintf(out, strchr(emails, ',') /* multiple addresses? */ ?
1069 "%s\t%s\t(%s)\t\t%s\n" : "%s\t%s\t%s\t\t%s\n",
1070 safe_str(db_fget(e.item, NICK)),
1071 safe_str(db_name_get(e.item)),
1073 safe_str(db_fget(e.item, NOTES))
1082 * end of pine addressbook export filter
1091 * these files should be parsed according to a certain
1092 * lay out, or the default if layout is not given, at
1093 * the moment only default is done...
1096 #define CSV_COMMENT_CHAR '#'
1097 #define CSV_DUPLICATE_SEPARATOR " "
1098 #define CSV_TABLE_SIZE(t) (sizeof (t) / sizeof *(t))
1100 static int csv_conv_table[] = {
1108 static int allcsv_conv_table[] = {
1127 static int palmcsv_conv_table[] = {
1128 NAME, /* Last name */
1129 NAME, /* First name */
1146 csv_convert_emails(char *s)
1154 for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
1155 if(i > MAX_LIST_ITEMS - 1) {
1163 csv_remove_quotes(char *s)
1165 char *copy, *trimmed;
1168 copy = trimmed = xstrdup(s);
1171 len = strlen(trimmed);
1172 if(trimmed[len - 1] == '\"' && *trimmed == '\"') {
1177 trimmed[len - 1] = 0;
1179 trimmed = xstrdup(trimmed);
1189 csv_field_to_item(int *table_base, size_t table_size, int field)
1191 if(field < table_size)
1192 return field_id(table_base[field]);
1198 csv_store_item(list_item item, int i, char *s)
1200 char *newstr = NULL;
1205 if( !(newstr = csv_remove_quotes(s)) )
1209 if (item[i] != NULL) {
1210 char *oldstr = item[i];
1212 item[i] = strconcat(newstr, CSV_DUPLICATE_SEPARATOR,
1225 csv_is_valid_quote_end(char *p)
1233 else if(!ISSPACE(*p))
1241 csv_is_valid_quote_start(char *p)
1246 else if(!ISSPACE(*p))
1254 csv_parse_line(char *line, int *table_base, size_t table_size)
1258 bool in_quote = FALSE;
1261 item = item_create();
1263 for(p = start = line, field = 0; *p; p++) {
1265 if(csv_is_valid_quote_end(p))
1268 if ( (((p - start) / sizeof (char)) < 2 ) &&
1269 csv_is_valid_quote_start(p) )
1273 if(*p == ',' && !in_quote) {
1275 csv_store_item(item,
1276 csv_field_to_item(table_base,table_size,field),
1285 csv_store_item(item, csv_field_to_item(table_base, table_size, field),
1288 csv_convert_emails(item_fget(item, EMAIL));
1289 add_item2database(item);
1294 csv_parse_file_common(FILE *in, int *conv_table, size_t table_size)
1299 line = getaline(in);
1301 if(line && *line && *line != CSV_COMMENT_CHAR)
1302 csv_parse_line(line, conv_table, table_size);
1311 csv_parse_file(FILE *in)
1313 return csv_parse_file_common(in, csv_conv_table,
1314 CSV_TABLE_SIZE(csv_conv_table));
1318 allcsv_parse_file(FILE *in)
1320 return csv_parse_file_common(in, allcsv_conv_table,
1321 CSV_TABLE_SIZE(allcsv_conv_table));
1325 palmcsv_parse_file(FILE *in)
1327 return csv_parse_file_common(in, palmcsv_conv_table,
1328 CSV_TABLE_SIZE(palmcsv_conv_table));
1332 * end of csv import filter
1336 * vCard import filter
1339 static char *vcard_fields[] = {
1341 "EMAIL", /* EMAIL */
1342 "ADR", /* ADDRESS */
1343 "ADR", /* ADDRESS2 - not used */
1347 "ADR", /* COUNTRY */
1349 "TEL", /* WORKPHONE */
1351 "TEL", /* MOBILEPHONE */
1352 "NICKNAME", /* NICK */
1355 NULL /* not implemented: ANNIVERSARY, ITEM_FIELDS */
1359 * mappings between vCard ADR field and abook's ADDRESS
1360 * see rfc2426 section 3.2.1
1362 static int vcard_address_fields[] = {
1363 -1, /* vCard(post office box) - not used */
1364 -1, /* vCard(the extended address) - not used */
1365 2, /* vCard(the street address) - ADDRESS */
1366 4, /* vCard(the locality) - CITY */
1367 5, /* vCard(the region) - STATE */
1368 6, /* vCard(the postal code) - ZIP */
1369 7 /* vCard(the country name) - COUNTRY */
1374 VCARD_KEY_ATTRIBUTE,
1379 vcard_get_line_element(char *line, int element)
1382 char *line_copy = 0;
1388 line_copy = xstrdup(line);
1390 /* make newline characters if exist end of string */
1391 for(i=0; line_copy[i]; i++) {
1392 if(line_copy[i] == '\r' || line_copy[i] == '\n') {
1393 line_copy[i] = '\0';
1398 /* separate key from value */
1399 for(i=0; line_copy[i]; i++) {
1400 if(line_copy[i] == ':') {
1401 line_copy[i] = '\0';
1403 value = &line_copy[i+1];
1408 /* separate key from key attributes */
1410 for(i=0; key[i]; i++) {
1413 key_attr = &key[i+1];
1422 result = xstrdup(key);
1424 case VCARD_KEY_ATTRIBUTE:
1426 result = xstrdup(key_attr);
1430 result = xstrdup(value);
1439 vcard_parse_email(list_item item, char *line)
1443 email = vcard_get_line_element(line, VCARD_VALUE);
1446 item[1] = strconcat(item[1], ",", email, 0);
1455 vcard_parse_address(list_item item, char *line)
1460 char *address_field;
1462 value = vcard_get_line_element(line, VCARD_VALUE);
1466 address_field = value;
1467 for(i=k=0; value[i]; i++) {
1468 if(value[i] == ';') {
1470 if(vcard_address_fields[k] >= 0) {
1471 item[vcard_address_fields[k]] = xstrdup(address_field);
1473 address_field = &value[i+1];
1475 if((k+1)==(sizeof(vcard_address_fields)/sizeof(*vcard_address_fields)))
1479 item[vcard_address_fields[k]] = xstrdup(address_field);
1484 vcard_parse_phone(list_item item, char *line)
1487 char *type = vcard_get_line_element(line, VCARD_KEY_ATTRIBUTE);
1488 char *value = vcard_get_line_element(line, VCARD_VALUE);
1490 /* set the standard number */
1492 item[index] = value;
1496 * see rfc2426 section 3.3.1
1498 else if (strstr(type, "TYPE=") == type){
1499 if (strcasestr(type, "home")) {
1500 item[index] = xstrdup(value);
1502 if (strcasestr(type, "work")) {
1503 item[index+1] = xstrdup(value);
1505 if (strcasestr(type, "fax")) {
1506 item[index+2] = xstrdup(value);
1508 if (strcasestr(type, "cell")) {
1509 item[index+3] = xstrdup(value);
1518 vcard_parse_line(list_item item, char *line)
1523 for(i=0; vcard_fields[i]; i++) {
1524 key = vcard_fields[i];
1526 if(!strncmp(key, line, strlen(key))) {
1528 vcard_parse_email(item, line);
1531 vcard_parse_address(item, line);
1534 vcard_parse_phone(item, line);
1537 item[i] = vcard_get_line_element(line, VCARD_VALUE);
1545 vcard_parse_item(FILE *in)
1548 list_item item = item_create();
1551 line = getaline(in);
1553 if(line && !strncmp("END:VCARD", line, 9)) {
1558 vcard_parse_line(item, line);
1563 add_item2database(item);
1568 vcard_parse_file(FILE *in)
1573 line = getaline(in);
1575 if(line && !strncmp("BEGIN:VCARD", line, 11)) {
1577 vcard_parse_item(in);
1588 * end of vCard import filter
1592 * csv addressbook export filters
1595 #define CSV_LAST (-1)
1596 #define CSV_UNDEFINED (-2)
1597 #define CSV_SPECIAL(X) (-3 - (X))
1598 #define CSV_IS_SPECIAL(X) ((X) <= -3)
1601 csv_export_common(FILE *out, struct db_enumerator e,
1602 int fields[], void (*special_func)(FILE *, int, int))
1606 db_enumerate_items(e) {
1607 for(i = 0; fields[i] != CSV_LAST; i++) {
1608 if(fields[i] == CSV_UNDEFINED)
1609 fprintf(out, "\"\"");
1610 else if(CSV_IS_SPECIAL(fields[i])) {
1612 (*special_func)(out, e.item, fields[i]);
1615 strchr(safe_str(database[e.item][field_idx(fields[i])]), ',') ||
1616 strchr(safe_str(database[e.item][field_idx(fields[i])]), '\"')) ?
1618 safe_str(database[e.item][field_idx(fields[i])])
1620 fprintf(out, "\"%s\"",
1621 safe_str(db_fget(e.item,fields[i])));
1623 if(fields[i + 1] != CSV_LAST)
1633 csv_export_database(FILE *out, struct db_enumerator e)
1635 int csv_export_fields[] = {
1644 csv_export_common(out, e, csv_export_fields, NULL);
1650 allcsv_export_database(FILE *out, struct db_enumerator e)
1653 * TODO: Should get these atomatically from abook_fileds
1656 int allcsv_export_fields[] = {
1677 fprintf(out, "\"NAME\",");
1678 fprintf(out, "\"EMAIL\",");
1679 fprintf(out, "\"ADDRESS\",");
1680 fprintf(out, "\"ADDRESS2\",");
1681 fprintf(out, "\"CITY\",");
1682 fprintf(out, "\"STATE\",");
1683 fprintf(out, "\"ZIP\",");
1684 fprintf(out, "\"COUNTRY\",");
1685 fprintf(out, "\"PHONE\",");
1686 fprintf(out, "\"WORKPHONE\",");
1687 fprintf(out, "\"FAX\",");
1688 fprintf(out, "\"MOBILEPHONE\",");
1689 fprintf(out, "\"NICK\",");
1690 fprintf(out, "\"URL\",");
1691 fprintf(out, "\"NOTES\",");
1692 fprintf(out, "\"ANNIVERSARY\"\n");
1694 csv_export_common(out, e, allcsv_export_fields, NULL);
1703 #define PALM_CSV_NAME CSV_SPECIAL(0)
1704 #define PALM_CSV_END CSV_SPECIAL(1)
1705 #define PALM_CSV_CAT CSV_SPECIAL(2)
1708 palm_split_and_write_name(FILE *out, char *name)
1714 if ( (p = strchr(name, ' ')) ) {
1718 fprintf(out, "\"%s\",\"" , p + 1);
1719 fwrite((void *)name, p - name, sizeof(char), out);
1722 fprintf(out, "\"%s\"", safe_str(name));
1727 palm_csv_handle_specials(FILE *out, int item, int field)
1731 palm_split_and_write_name(out, db_name_get(item));
1734 fprintf(out, "\"abook\"");
1737 fprintf(out, "\"0\"");
1745 palm_export_database(FILE *out, struct db_enumerator e)
1747 int palm_export_fields[] = {
1748 PALM_CSV_NAME, /* LASTNAME, FIRSTNAME */
1749 CSV_UNDEFINED, /* TITLE */
1750 CSV_UNDEFINED, /* COMPANY */
1751 WORKPHONE, /* WORK PHONE */
1752 PHONE, /* HOME PHONE */
1754 MOBILEPHONE, /* OTHER */
1756 ADDRESS, /* ADDRESS */
1760 COUNTRY, /* COUNTRY */
1761 NICK, /* DEFINED 1 */
1762 URL, /* DEFINED 2 */
1763 CSV_UNDEFINED, /* DEFINED 3 */
1764 CSV_UNDEFINED, /* DEFINED 4 */
1766 PALM_CSV_END, /* "0" */
1767 PALM_CSV_CAT, /* CATEGORY */
1771 csv_export_common(out, e, palm_export_fields, palm_csv_handle_specials);
1777 * end of csv export filters
1781 * GnomeCard (VCard) addressbook export filter
1785 gcrd_export_database(FILE *out, struct db_enumerator e)
1789 abook_list *emails, *em;
1791 db_enumerate_items(e) {
1792 fprintf(out, "BEGIN:VCARD\r\nFN:%s\r\n",
1793 safe_str(db_name_get(e.item)));
1795 name = get_surname(db_name_get(e.item));
1796 for( j = strlen(db_name_get(e.item)) - 1; j >= 0; j-- ) {
1797 if((db_name_get(e.item))[j] == ' ')
1800 fprintf(out, "N:%s;%.*s\r\n",
1803 safe_str(db_name_get(e.item))
1808 if(db_fget(e.item, ADDRESS))
1809 fprintf(out, "ADR:;;%s;%s;%s;%s;%s;%s\r\n",
1810 safe_str(db_fget(e.item, ADDRESS)),
1811 safe_str(db_fget(e.item, ADDRESS2)),
1812 safe_str(db_fget(e.item, CITY)),
1813 safe_str(db_fget(e.item, STATE)),
1814 safe_str(db_fget(e.item, ZIP)),
1815 safe_str(db_fget(e.item, COUNTRY))
1818 if(db_fget(e.item, PHONE))
1819 fprintf(out, "TEL;HOME:%s\r\n",
1820 db_fget(e.item, PHONE));
1821 if(db_fget(e.item, WORKPHONE))
1822 fprintf(out, "TEL;WORK:%s\r\n",
1823 db_fget(e.item, WORKPHONE));
1824 if(db_fget(e.item, FAX))
1825 fprintf(out, "TEL;FAX:%s\r\n",
1826 db_fget(e.item, FAX));
1827 if(db_fget(e.item, MOBILEPHONE))
1828 fprintf(out, "TEL;CELL:%s\r\n",
1829 db_fget(e.item, MOBILEPHONE));
1831 tmp = db_email_get(e.item);
1833 emails = csv_to_abook_list(tmp);
1835 for(em = emails; em; em = em->next)
1836 fprintf(out, "EMAIL;INTERNET:%s\r\n", em->data);
1838 abook_list_free(&emails);
1842 if(db_fget(e.item, NOTES))
1843 fprintf(out, "NOTE:%s\r\n",
1844 db_fget(e.item, NOTES));
1845 if(db_fget(e.item, URL))
1846 fprintf(out, "URL:%s\r\n",
1847 db_fget(e.item, URL));
1849 fprintf(out, "END:VCARD\r\n\r\n");
1857 * end of GnomeCard export filter
1862 * mutt alias export filter
1866 mutt_alias_genalias(int i)
1870 if(db_fget(i, NICK))
1871 return xstrdup(db_fget(i, NICK));
1873 tmp = xstrdup(db_name_get(i));
1875 if( ( pos = strchr(tmp, ' ') ) )
1884 mutt_alias_export(FILE *out, struct db_enumerator e)
1886 char email[MAX_EMAIL_LEN];
1888 int email_addresses;
1891 db_enumerate_items(e) {
1892 alias = mutt_alias_genalias(e.item);
1893 get_first_email(email, e.item);
1895 /* do not output contacts without email address */
1896 /* cause this does not make sense in mutt aliases */
1899 /* output first email address */
1900 fprintf(out, "alias %s %s <%s>\n",
1902 db_name_get(e.item),
1905 /* number of email addresses */
1906 email_addresses = 1;
1907 ptr = db_email_get(e.item);
1908 while (*ptr != '\0') {
1915 /* output other email addresses */
1916 while (email_addresses-- > 1) {
1917 roll_emails(e.item, ROTATE_RIGHT);
1918 get_first_email(email, e.item);
1919 fprintf(out, "alias %s__%s %s <%s>\n",
1922 db_name_get(e.item),
1925 roll_emails(e.item, ROTATE_RIGHT);
1934 * end of mutt alias export filter
1939 * printable export filter
1944 text_write_address_us(FILE *out, int i) {
1945 fprintf(out, "\n%s", db_fget(i, ADDRESS));
1947 if(db_fget(i, ADDRESS2))
1948 fprintf(out, "\n%s", db_fget(i, ADDRESS2));
1950 if(db_fget(i, CITY))
1951 fprintf(out, "\n%s", db_fget(i, CITY));
1953 if(db_fget(i, STATE) || db_fget(i, ZIP)) {
1956 if(db_fget(i, STATE)) {
1957 fprintf(out, "%s", db_fget(i, STATE));
1963 fprintf(out, "%s", db_fget(i, ZIP));
1966 if(db_fget(i, COUNTRY))
1967 fprintf(out, "\n%s", db_fget(i, COUNTRY));
1972 text_write_address_uk(FILE *out, int i) {
1975 for(j = ADDRESS; j <= COUNTRY; j++)
1977 fprintf(out, "\n%s", db_fget(i, j));
1981 text_write_address_eu(FILE *out, int i) {
1982 fprintf(out, "\n%s", db_fget(i, ADDRESS));
1984 if(db_fget(i, ADDRESS2))
1985 fprintf(out, "\n%s", db_fget(i, ADDRESS2));
1987 if(db_fget(i, ZIP) || db_fget(i, CITY)) {
1990 if(db_fget(i, ZIP)) {
1991 fprintf(out, "%s", db_fget(i, ZIP));
1992 if(db_fget(i, CITY))
1996 fprintf(out, "%s", safe_str(db_fget(i, CITY)));
1999 if(db_fget(i, STATE))
2000 fprintf(out, "\n%s", db_fget(i, STATE));
2002 if(db_fget(i, COUNTRY))
2003 fprintf(out, "\n%s", db_fget(i, COUNTRY));
2007 text_export_database(FILE * out, struct db_enumerator e)
2009 abook_list *emails, *em;
2011 char *realname = get_real_name(), *str = NULL, *tmp;
2012 char *style = opt_get_str(STR_ADDRESS_STYLE);
2015 "-----------------------------------------\n%s's address book\n"
2016 "-----------------------------------------\n\n\n",
2020 db_enumerate_items(e) {
2022 "-----------------------------------------\n\n");
2023 fprintf(out, "%s", db_name_get(e.item));
2024 if(db_fget(e.item, NICK) && *db_fget(e.item, NICK))
2025 fprintf(out, "\n(%s)", db_fget(e.item, NICK));
2028 tmp = db_email_get(e.item);
2030 emails = csv_to_abook_list(tmp);
2033 for(em = emails; em; em = em->next)
2034 fprintf(out, "%s\n", em->data);
2036 abook_list_free(&emails);
2040 if(db_fget(e.item, ADDRESS)) {
2041 if(!safe_strcmp(style, "us")) /* US like */
2042 text_write_address_us(out, e.item);
2043 else if(!safe_strcmp(style, "uk")) /* UK like */
2044 text_write_address_uk(out, e.item);
2046 text_write_address_eu(out, e.item);
2051 if((db_fget(e.item, PHONE)) ||
2052 (db_fget(e.item, WORKPHONE)) ||
2053 (db_fget(e.item, FAX)) ||
2054 (db_fget(e.item, MOBILEPHONE))) {
2056 for(j = PHONE; j <= MOBILEPHONE; j++)
2057 if(db_fget(e.item, j)) {
2058 get_field_info(field_id(j),
2060 fprintf(out, "%s: %s\n", str,
2061 db_fget(e.item, j));
2065 if(db_fget(e.item, URL))
2066 fprintf(out, "\n%s\n", db_fget(e.item, URL));
2067 if(db_fget(e.item, NOTES))
2068 fprintf(out, "\n%s\n", db_fget(e.item, NOTES));
2073 fprintf(out, "-----------------------------------------\n");
2079 * end of printable export filter
2083 * elm alias export filter
2087 elm_alias_export(FILE *out, struct db_enumerator e)
2089 char email[MAX_EMAIL_LEN];
2092 db_enumerate_items(e) {
2093 alias = mutt_alias_genalias(e.item);
2094 get_first_email(email, e.item);
2095 fprintf(out, "%s = %s = %s\n",alias,db_name_get(e.item),email);
2103 * end of elm alias export filter
2108 * Spruce export filter
2112 spruce_export_database (FILE *out, struct db_enumerator e)
2114 char email[MAX_EMAIL_LEN];
2116 fprintf(out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
2118 db_enumerate_items(e) {
2119 get_first_email(email, e.item);
2120 if(strcmp(email, "")) {
2121 fprintf(out, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
2123 db_name_get(e.item),
2125 safe_str(db_fget(e.item, NOTES))
2130 fprintf (out, "# End of address book file.\n");
2136 * end of Spruce export filter
2140 * wanderlust addressbook export filter
2144 wl_export_database(FILE *out, struct db_enumerator e)
2146 char email[MAX_EMAIL_LEN];
2148 fprintf(out, "# Wanderlust address book written by %s\n\n", PACKAGE);
2149 db_enumerate_items(e) {
2150 get_first_email(email, e.item);
2153 "%s\t\"%s\"\t\"%s\"\n",
2155 safe_str(db_fget(e.item, NICK)),
2156 safe_str(db_name_get(e.item))
2161 fprintf (out, "\n# End of address book file.\n");
2167 * end of wanderlust addressbook export filter
2171 * BSD calendar export filter
2175 bsdcal_export_database(FILE *out, struct db_enumerator e)
2177 db_enumerate_items(e) {
2178 int year, month = 0, day = 0;
2179 char *anniversary = db_fget(e.item, ANNIVERSARY);
2182 if(!parse_date_string(anniversary, &day, &month, &year))
2186 _("%02d/%02d\tAnniversary of %s\n"),
2189 safe_str(db_name_get(e.item))
2198 * end of BSD calendar export filter