use automake 1.11, autoconf 2.65
[abook.git] / filter.c
blob567027cababfc87967a86bbb86133b50ae62461c
2 /*
3 * $Id: filter.c,v 1.55 2006/09/06 02:46:44 cduval Exp $
5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
8 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <pwd.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include "abook_curses.h"
18 #include "filter.h"
19 #include "abook.h"
20 #include "database.h"
21 #include "edit.h"
22 #include "gettext.h"
23 #include "list.h"
24 #include "misc.h"
25 #include "options.h"
26 #include "ui.h"
27 #include "xmalloc.h"
28 #include <assert.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 },
80 { "\0", NULL, NULL }
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 },
98 { "\0", NULL, NULL }
102 * common functions
105 void
106 print_filters()
108 int i;
110 puts(_("input:"));
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));
115 putchar('\n');
117 puts(_("output:"));
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));
122 putchar('\n');
125 static int
126 number_of_output_filters()
128 int i;
130 for(i=0; *e_filters[i].filtname ; i++)
133 return i;
136 static int
137 number_of_input_filters()
139 int i;
141 for(i=0; *i_filters[i].filtname ; i++)
144 return i;
147 static char *
148 get_real_name()
150 char *username = getenv("USER");
151 struct passwd *pwent;
152 int rtn;
153 char *tmp;
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) {
162 free(tmp);
163 return xstrdup(username);
164 } else
165 return tmp;
169 * import
172 static int i_read_file(char *filename, int (*func) (FILE *in));
174 static void
175 import_screen()
177 int i;
179 clear();
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"));
196 import_database()
198 int filter;
199 char *filename;
200 int tmp = db_n_items();
202 import_screen();
204 filter = getch() - 'a';
205 if(filter == 'x' - 'a' ||
206 filter >= number_of_input_filters() || filter < 0) {
207 refresh_screen();
208 return 1;
211 mvaddstr(5+filter, 2, "->");
213 filename = ask_filename(_("Filename: "));
214 if(!filename) {
215 refresh_screen();
216 return 2;
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"));
224 refresh_screen();
225 free(filename);
227 return 0;
232 static int
233 i_read_file(char *filename, int (*func) (FILE *in))
235 FILE *in;
236 int ret = 0;
238 if( (in = abook_fopen( filename, "r" )) == NULL )
239 return 1;
241 ret = (*func) (in);
243 fclose(in);
245 return ret;
249 import_file(char filtname[FILTNAME_LEN], char *filename)
251 int i;
252 int tmp = db_n_items();
253 int ret = 0;
255 for(i=0;; i++) {
256 if(! strncasecmp(i_filters[i].filtname, filtname,
257 FILTNAME_LEN) )
258 break;
259 if(! *i_filters[i].filtname) {
260 i = -1;
261 break;
265 if(i < 0)
266 return -1;
268 if(!strcmp(filename, "-")) {
269 struct stat s;
270 if((fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode))
271 ret = 1;
272 else
273 ret = (*i_filters[i].func) (stdin);
274 } else
275 ret = i_read_file(filename, i_filters[i].func);
277 if(tmp == db_n_items())
278 ret = 1;
280 return ret;
284 * export
287 static int e_write_file(char *filename,
288 int (*func) (FILE *in, struct db_enumerator e), int mode);
290 static void
291 export_screen()
293 int i;
295 clear();
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"));
313 export_database()
315 int filter;
316 int enum_mode = ENUM_ALL;
317 char *filename;
319 export_screen();
321 filter = getch() - 'a';
322 if(filter == 'x' - 'a' ||
323 filter >= number_of_output_filters() || filter < 0) {
324 refresh_screen();
325 return 1;
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)) {
334 case 1:
335 break;
336 case 2:
337 enum_mode = ENUM_SELECTED;
338 break;
339 case 0:
340 case 3:
341 refresh_screen();
342 return 1;
344 clear_statusline();
347 filename = ask_filename(_("Filename: "));
348 if(!filename) {
349 refresh_screen();
350 return 2;
353 if( e_write_file(filename, e_filters[filter].func, enum_mode))
354 statusline_msg(_("Error occured while exporting"));
356 refresh_screen();
357 free(filename);
359 return 0;
362 static int
363 e_write_file(char *filename, int (*func) (FILE *in, struct db_enumerator e),
364 int mode)
366 FILE *out;
367 int ret = 0;
368 struct db_enumerator enumerator = init_db_enumerator(mode);
370 if((out = fopen(filename, "a")) == NULL)
371 return 1;
373 if(ftell(out))
374 return 1;
376 ret = (*func) (out, enumerator);
378 fclose(out);
380 return ret;
384 fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode)
386 int i;
387 struct db_enumerator e = init_db_enumerator(enum_mode);
389 for(i=0;; i++) {
390 if(!strncasecmp(e_filters[i].filtname, filtname,
391 FILTNAME_LEN))
392 break;
393 if(!*e_filters[i].filtname) {
394 i = -1;
395 break;
399 return (e_filters[i].func) (handle, e);
405 export_file(char filtname[FILTNAME_LEN], char *filename)
407 const int mode = ENUM_ALL;
408 int i;
409 int ret = 0;
410 struct db_enumerator e = init_db_enumerator(mode);
412 for(i=0;; i++) {
413 if(!strncasecmp(e_filters[i].filtname, filtname,
414 FILTNAME_LEN))
415 break;
416 if(!*e_filters[i].filtname) {
417 i = -1;
418 break;
422 if(i < 0)
423 return -1;
425 if(!strcmp(filename, "-"))
426 ret = (e_filters[i].func) (stdout, e);
427 else
428 ret = e_write_file(filename, e_filters[i].func, mode);
430 return ret;
434 * end of common functions
438 * ldif import
441 #include "ldif.h"
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 = {
450 "cn",
451 "mail",
452 "streetaddress",
453 "streetaddress2",
454 "locality",
455 "st",
456 "postalcode",
457 "countryname",
458 "homephone",
459 "description",
460 "homeurl",
461 "facsimiletelephonenumber",
462 "cellphone",
463 "xmozillaanyphone",
464 "xmozillanickname",
465 "objectclass", /* this must be the last entry */
468 static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
469 NAME, /* "cn" */
470 EMAIL, /* "mail" */
471 ADDRESS, /* "streetaddress" */
472 ADDRESS2, /* "streetaddress2" */
473 CITY, /* "locality" */
474 STATE, /* "st" */
475 ZIP, /* "postalcode" */
476 COUNTRY, /* "countryname" */
477 PHONE, /* "homephone" */
478 NOTES, /* "description" */
479 URL, /* "homeurl" */
480 FAX, /* "facsimiletelephonenumber" */
481 MOBILEPHONE, /* "cellphone" */
482 WORKPHONE, /* "xmozillaanyphone" */
483 NICK, /* "xmozillanickname" */
484 -1, /* "objectclass" */ /* this must be the last entry */
488 static char *
489 ldif_read_line(FILE *in)
491 char *buf = NULL;
492 char *ptr, *tmp;
493 long pos;
494 int i;
496 for(i = 1;;i++) {
497 char *line;
499 pos = ftell(in);
500 line = getaline(in);
502 if(feof(in) || !line)
503 break;
505 if(i == 1) {
506 buf = line;
507 continue;
510 if(*line != ' ') {
511 fseek(in, pos, SEEK_SET); /* fixme ! */
512 free(line);
513 break;
516 ptr = line;
517 while( *ptr == ' ')
518 ptr++;
520 tmp = buf;
521 buf = strconcat(buf, ptr, NULL);
522 free(tmp);
523 free(line);
526 if(buf && *buf == '#' ) {
527 free(buf);
528 return NULL;
531 return buf;
534 static void
535 ldif_add_item(ldif_item li)
537 list_item item;
538 int i;
540 item = item_create();
542 if(!li[LDIF_ITEM_FIELDS -1])
543 goto bail_out;
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);
553 bail_out:
554 for(i=0; i < LDIF_ITEM_FIELDS; i++)
555 xfree(li[i]);
556 item_free(&item);
560 static void
561 ldif_convert(ldif_item item, char *type, char *value)
563 int i;
565 if(!strcmp(type, "dn")) {
566 ldif_add_item(item);
567 return;
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))
574 break;
576 if(item_fget(item, i))
577 free(item_fget(item, i));
579 item_fput(item, i, xstrdup(value));
584 static int
585 ldif_parse_file(FILE *handle)
587 char *line = NULL;
588 char *type, *value;
589 int vlen;
590 ldif_item item;
592 memset(item, 0, sizeof(item));
594 do {
595 if( !(line = ldif_read_line(handle)) )
596 continue;
598 if(-1 == (str_parse_line(line, &type, &value, &vlen))) {
599 xfree(line);
600 continue; /* just skip the errors */
603 ldif_fix_string(value);
605 ldif_convert(item, type, value);
607 xfree(line);
608 } while ( !feof(handle) );
610 ldif_convert(item, "dn", "");
612 return 0;
615 static void
616 ldif_fix_string(char *str)
618 int i, j;
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 :
623 str[j] );
625 str[i] = 0;
629 * end of ldif import
633 * mutt alias import filter
636 #include "getname.h"
638 static int
639 mutt_read_line(FILE *in, char **alias, char **rest)
641 char *line, *ptr, *tmp;
642 size_t alias_len;
644 if( !(line = ptr = getaline(in)) )
645 return 1; /* error / EOF */
647 SKIPWS(ptr);
649 if(strncmp("alias", ptr, 5)) {
650 free(line);
651 return 1;
654 ptr += 5;
656 SKIPWS(ptr);
658 tmp = ptr;
660 while( ! ISSPACE(*ptr) )
661 ptr++;
663 alias_len = (size_t)(ptr - tmp);
665 if(alias)
666 *alias = xmalloc_inc(alias_len, 1);
668 strncpy(*alias, tmp, alias_len);
669 *(*alias + alias_len) = 0;
671 SKIPWS(ptr);
673 *rest = xstrdup(ptr);
675 free(line);
676 return 0;
679 static void
680 mutt_fix_quoting(char *p)
682 char *escape = 0;
684 for(; *p; p++) {
685 switch(*p) {
686 case '\"':
687 if(escape)
688 *escape = ' ';
689 break;
690 case '\\':
691 escape = p;
692 break;
693 default:
694 escape = 0;
699 static void
700 mutt_parse_email(list_item item)
702 char *line = item_fget(item, NAME);
703 char *tmp;
704 char *name, *email;
705 #if 0
706 char *start = line;
707 int i = 0;
708 #endif
710 mutt_fix_quoting(line);
711 tmp = strconcat("From: ", line, NULL);
712 getname(tmp, &name, &email);
713 free(tmp);
715 if(name)
716 item_fput(item, NAME, name);
717 else
718 return;
720 if(email)
721 item_fput(item, EMAIL, email);
722 else
723 return;
726 * this is completely broken
728 #if 0
729 while( (start = strchr(start, ',')) && i++ < MAX_EMAILS - 1) {
730 tmp = strconcat("From: ", ++start, NULL);
731 getname(tmp, &name, &email);
732 free(tmp);
733 free(name);
734 if(email) {
735 if(*email) {
736 tmp = strconcat(item[EMAIL], ",", email, NULL);
737 free(item[EMAIL]);
738 item[EMAIL] = tmp;
739 } else {
740 xfree(email);
744 #endif
747 static int
748 mutt_parse_file(FILE *in)
750 list_item item = item_create();
752 for(;;) {
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);
761 if(feof(in)) {
762 item_empty(item);
763 break;
766 add_item2database(item);
768 item_free(&item);
770 return 0;
774 * end of mutt alias import filter
779 * ldif export filter
782 static void
783 ldif_fput_type_and_value(FILE *out,char *type, char *value )
785 char *tmp;
787 tmp = ldif_type_and_value(type, value, strlen(value));
789 fputs(tmp, out);
791 free(tmp);
794 static int
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) {
802 char *tmp;
803 int j;
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);
809 free(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,
818 ldif_field_names[j],
819 db_fget(e.item,
820 ldif_conv_table[j]));
824 fprintf(out, "objectclass: top\n"
825 "objectclass: person\n\n");
828 return 0;
832 * end of ldif export filter
836 * html 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;
844 static void
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);
851 if(l->next)
852 fprintf(out, ", ");
855 abook_list_free(&l);
858 static int
859 html_export_database(FILE *out, struct db_enumerator e)
861 struct list_field f;
862 struct index_elem *cur;
864 if(list_is_empty())
865 return 2;
867 init_index();
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)
875 continue;
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>");
883 continue;
884 } else {
885 fprintf(out, "<td>%s</td>", safe_str(f.data));
888 fprintf(out, "</tr>\n");
891 html_export_write_tail(out);
893 return 0;
896 static void
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>",
904 realname );
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)
912 continue;
914 get_field_info(cur->d.field.id, NULL, &str, NULL);
915 fprintf(out, "<th>%s</th>", str);
917 fprintf(out, "</tr>\n\n");
919 free(realname);
922 static void
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
940 static void
941 pine_fixbuf(char *buf)
943 int i,j;
945 for(i = 0,j = 0; j < (int)strlen(buf); i++, j++)
946 buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
949 static void
950 pine_convert_emails(char *s)
952 int i;
953 char *tmp;
955 if(s == NULL || *s != '(')
956 return;
958 for(i = 0; s[i]; i++)
959 s[i] = s[i + 1];
961 if( ( tmp = strchr(s,')')) )
962 *tmp = '\0';
964 for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
965 if(i > MAX_LIST_ITEMS - 1) {
966 *tmp = '\0';
967 break;
972 static void
973 pine_parse_buf(char *buf)
975 list_item item;
976 char *start = buf;
977 char *end;
978 char tmp[PINE_BUF_SIZE];
979 int i, len, last;
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')) )
986 last=1;
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);
994 tmp[len] = 0;
995 if(*tmp)
996 item_fput(item, pine_conv_table[i],
997 xstrdup(tmp));
999 start = end + 1;
1002 pine_convert_emails(item_fget(item, EMAIL));
1003 add_item2database(item);
1004 item_free(&item);
1008 #define LINESIZE 1024
1010 static int
1011 pine_parse_file(FILE *in)
1013 char line[LINESIZE];
1014 char *buf = NULL;
1015 char *ptr;
1016 int i;
1018 fgets(line, LINESIZE, in);
1020 while(!feof(in)) {
1021 for(i = 2;;i++) {
1022 buf = xrealloc(buf, i*LINESIZE);
1023 if(i == 2)
1024 strcpy(buf, line);
1025 fgets(line, LINESIZE, in);
1026 ptr=(char *)&line;
1027 if(*ptr != ' ' || feof(in))
1028 break;
1029 else
1030 while(*ptr == ' ')
1031 ptr++;
1033 strcat(buf, ptr);
1035 if(*buf == '#') {
1036 xfree(buf);
1037 continue;
1039 pine_fixbuf(buf);
1041 pine_parse_buf(buf);
1043 xfree(buf);
1046 return 0;
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
1061 static int
1062 pine_export_database(FILE *out, struct db_enumerator e)
1064 char *emails;
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)),
1072 emails,
1073 safe_str(db_fget(e.item, NOTES))
1075 free(emails);
1078 return 0;
1082 * end of pine addressbook export filter
1087 * csv import filter
1090 /* FIXME
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[] = {
1101 NAME,
1102 EMAIL,
1103 PHONE,
1104 NOTES,
1105 NICK
1108 static int allcsv_conv_table[] = {
1109 NAME,
1110 EMAIL,
1111 ADDRESS,
1112 ADDRESS2,
1113 CITY,
1114 STATE,
1115 ZIP,
1116 COUNTRY,
1117 PHONE,
1118 WORKPHONE,
1119 FAX,
1120 MOBILEPHONE,
1121 NICK,
1122 URL,
1123 NOTES,
1124 ANNIVERSARY
1127 static int palmcsv_conv_table[] = {
1128 NAME, /* Last name */
1129 NAME, /* First name */
1130 NOTES, /* Title */
1131 NICK, /* Company */
1132 WORKPHONE,
1133 PHONE,
1134 FAX,
1135 MOBILEPHONE,
1136 EMAIL,
1137 ADDRESS,
1138 CITY,
1139 STATE,
1140 ZIP,
1141 COUNTRY,
1142 ANNIVERSARY,
1145 static void
1146 csv_convert_emails(char *s)
1148 int i;
1149 char *tmp;
1151 if(s == NULL)
1152 return;
1154 for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
1155 if(i > MAX_LIST_ITEMS - 1) {
1156 *tmp = 0;
1157 break;
1162 static char *
1163 csv_remove_quotes(char *s)
1165 char *copy, *trimmed;
1166 int len;
1168 copy = trimmed = xstrdup(s);
1169 strtrim(trimmed);
1171 len = strlen(trimmed);
1172 if(trimmed[len - 1] == '\"' && *trimmed == '\"') {
1173 if(len < 3) {
1174 xfree(copy);
1175 return NULL;
1177 trimmed[len - 1] = 0;
1178 trimmed++;
1179 trimmed = xstrdup(trimmed);
1180 free(copy);
1181 return trimmed;
1184 xfree(copy);
1185 return xstrdup(s);
1188 static int
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]);
1194 return -1;
1197 static void
1198 csv_store_item(list_item item, int i, char *s)
1200 char *newstr = NULL;
1202 if(!s || !*s)
1203 return;
1205 if( !(newstr = csv_remove_quotes(s)) )
1206 return;
1208 if(i >= 0) {
1209 if (item[i] != NULL) {
1210 char *oldstr = item[i];
1212 item[i] = strconcat(newstr, CSV_DUPLICATE_SEPARATOR,
1213 oldstr, NULL);
1214 xfree(newstr);
1215 xfree(oldstr);
1216 } else {
1217 item[i] = newstr;
1219 } else {
1220 xfree(newstr);
1224 static int
1225 csv_is_valid_quote_end(char *p)
1227 if(*p != '\"')
1228 return FALSE;
1230 for(p++; *p; p++) {
1231 if(*p == ',')
1232 return TRUE;
1233 else if(!ISSPACE(*p))
1234 return FALSE;
1237 return TRUE;
1240 static int
1241 csv_is_valid_quote_start(char *p)
1243 for(; *p; p++) {
1244 if(*p == '\"')
1245 return TRUE;
1246 else if(!ISSPACE(*p))
1247 return FALSE;
1250 return FALSE;
1253 static void
1254 csv_parse_line(char *line, int *table_base, size_t table_size)
1256 char *p, *start;
1257 int field;
1258 bool in_quote = FALSE;
1259 list_item item;
1261 item = item_create();
1263 for(p = start = line, field = 0; *p; p++) {
1264 if(in_quote) {
1265 if(csv_is_valid_quote_end(p))
1266 in_quote = FALSE;
1267 } else {
1268 if ( (((p - start) / sizeof (char)) < 2 ) &&
1269 csv_is_valid_quote_start(p) )
1270 in_quote = TRUE;
1273 if(*p == ',' && !in_quote) {
1274 *p = 0;
1275 csv_store_item(item,
1276 csv_field_to_item(table_base,table_size,field),
1277 start);
1278 field++;
1279 start = p + 1;
1283 * store last field
1285 csv_store_item(item, csv_field_to_item(table_base, table_size, field),
1286 start);
1288 csv_convert_emails(item_fget(item, EMAIL));
1289 add_item2database(item);
1290 item_free(&item);
1293 static int
1294 csv_parse_file_common(FILE *in, int *conv_table, size_t table_size)
1296 char *line = NULL;
1298 while(!feof(in)) {
1299 line = getaline(in);
1301 if(line && *line && *line != CSV_COMMENT_CHAR)
1302 csv_parse_line(line, conv_table, table_size);
1304 xfree(line);
1307 return 0;
1310 static int
1311 csv_parse_file(FILE *in)
1313 return csv_parse_file_common(in, csv_conv_table,
1314 CSV_TABLE_SIZE(csv_conv_table));
1317 static int
1318 allcsv_parse_file(FILE *in)
1320 return csv_parse_file_common(in, allcsv_conv_table,
1321 CSV_TABLE_SIZE(allcsv_conv_table));
1324 static int
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[] = {
1340 "FN", /* NAME */
1341 "EMAIL", /* EMAIL */
1342 "ADR", /* ADDRESS */
1343 "ADR", /* ADDRESS2 - not used */
1344 "ADR", /* CITY */
1345 "ADR", /* STATE */
1346 "ADR", /* ZIP */
1347 "ADR", /* COUNTRY */
1348 "TEL", /* PHONE */
1349 "TEL", /* WORKPHONE */
1350 "TEL", /* FAX */
1351 "TEL", /* MOBILEPHONE */
1352 "NICKNAME", /* NICK */
1353 "URL", /* URL */
1354 "NOTE", /* NOTES */
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 */
1372 enum {
1373 VCARD_KEY = 0,
1374 VCARD_KEY_ATTRIBUTE,
1375 VCARD_VALUE,
1378 static char *
1379 vcard_get_line_element(char *line, int element)
1381 int i;
1382 char *line_copy = 0;
1383 char *result = 0;
1384 char *key = 0;
1385 char *key_attr = 0;
1386 char *value = 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';
1394 break;
1398 /* separate key from value */
1399 for(i=0; line_copy[i]; i++) {
1400 if(line_copy[i] == ':') {
1401 line_copy[i] = '\0';
1402 key = line_copy;
1403 value = &line_copy[i+1];
1404 break;
1408 /* separate key from key attributes */
1409 if (key) {
1410 for(i=0; key[i]; i++) {
1411 if(key[i] == ';') {
1412 key[i] = '\0';
1413 key_attr = &key[i+1];
1414 break;
1419 switch(element) {
1420 case VCARD_KEY:
1421 if(key)
1422 result = xstrdup(key);
1423 break;
1424 case VCARD_KEY_ATTRIBUTE:
1425 if(key_attr)
1426 result = xstrdup(key_attr);
1427 break;
1428 case VCARD_VALUE:
1429 if(value)
1430 result = xstrdup(value);
1431 break;
1434 xfree(line_copy);
1435 return result;
1438 static void
1439 vcard_parse_email(list_item item, char *line)
1441 char *email;
1443 email = vcard_get_line_element(line, VCARD_VALUE);
1445 if(item[1]) {
1446 item[1] = strconcat(item[1], ",", email, 0);
1447 xfree(email);
1449 else {
1450 item[1] = email;
1454 static void
1455 vcard_parse_address(list_item item, char *line)
1457 int i;
1458 int k;
1459 char *value;
1460 char *address_field;
1462 value = vcard_get_line_element(line, VCARD_VALUE);
1463 if(!value)
1464 return;
1466 address_field = value;
1467 for(i=k=0; value[i]; i++) {
1468 if(value[i] == ';') {
1469 value[i] = '\0';
1470 if(vcard_address_fields[k] >= 0) {
1471 item[vcard_address_fields[k]] = xstrdup(address_field);
1473 address_field = &value[i+1];
1474 k++;
1475 if((k+1)==(sizeof(vcard_address_fields)/sizeof(*vcard_address_fields)))
1476 break;
1479 item[vcard_address_fields[k]] = xstrdup(address_field);
1480 xfree(value);
1483 static void
1484 vcard_parse_phone(list_item item, char *line)
1486 int index = 8;
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 */
1491 if (!type) {
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);
1512 xfree(type);
1513 xfree(value);
1517 static void
1518 vcard_parse_line(list_item item, char *line)
1520 int i;
1521 char *key;
1523 for(i=0; vcard_fields[i]; i++) {
1524 key = vcard_fields[i];
1526 if(!strncmp(key, line, strlen(key))) {
1527 if(i == 1) {
1528 vcard_parse_email(item, line);
1530 else if(i == 2) {
1531 vcard_parse_address(item, line);
1533 else if(i == 8) {
1534 vcard_parse_phone(item, line);
1536 else {
1537 item[i] = vcard_get_line_element(line, VCARD_VALUE);
1539 break;
1544 static void
1545 vcard_parse_item(FILE *in)
1547 char *line = NULL;
1548 list_item item = item_create();
1550 while(!feof(in)) {
1551 line = getaline(in);
1553 if(line && !strncmp("END:VCARD", line, 9)) {
1554 xfree(line);
1555 break;
1557 else if(line) {
1558 vcard_parse_line(item, line);
1559 xfree(line);
1563 add_item2database(item);
1564 item_free(&item);
1567 static int
1568 vcard_parse_file(FILE *in)
1570 char *line = NULL;
1572 while(!feof(in)) {
1573 line = getaline(in);
1575 if(line && !strncmp("BEGIN:VCARD", line, 11)) {
1576 xfree(line);
1577 vcard_parse_item(in);
1579 else if(line) {
1580 xfree(line);
1584 return 0;
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)
1600 static int
1601 csv_export_common(FILE *out, struct db_enumerator e,
1602 int fields[], void (*special_func)(FILE *, int, int))
1604 int i;
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])) {
1611 if(special_func)
1612 (*special_func)(out, e.item, fields[i]);
1613 } else
1614 /*fprintf(out,(
1615 strchr(safe_str(database[e.item][field_idx(fields[i])]), ',') ||
1616 strchr(safe_str(database[e.item][field_idx(fields[i])]), '\"')) ?
1617 "\"%s\"" : "%s",
1618 safe_str(database[e.item][field_idx(fields[i])])
1619 );*/
1620 fprintf(out, "\"%s\"",
1621 safe_str(db_fget(e.item,fields[i])));
1623 if(fields[i + 1] != CSV_LAST)
1624 fputc(',', out);
1626 fputc('\n', out);
1629 return 0;
1632 static int
1633 csv_export_database(FILE *out, struct db_enumerator e)
1635 int csv_export_fields[] = {
1636 NAME,
1637 EMAIL,
1638 PHONE,
1639 NOTES,
1640 NICK,
1641 CSV_LAST
1644 csv_export_common(out, e, csv_export_fields, NULL);
1646 return 0;
1649 static int
1650 allcsv_export_database(FILE *out, struct db_enumerator e)
1653 * TODO: Should get these atomatically from abook_fileds
1654 * - JH
1656 int allcsv_export_fields[] = {
1657 NAME,
1658 EMAIL,
1659 ADDRESS,
1660 ADDRESS2,
1661 CITY,
1662 STATE,
1663 ZIP,
1664 COUNTRY,
1665 PHONE,
1666 WORKPHONE,
1667 FAX,
1668 MOBILEPHONE,
1669 NICK,
1670 URL,
1671 NOTES,
1672 ANNIVERSARY,
1673 CSV_LAST
1676 fprintf(out, "#");
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);
1696 return 0;
1700 * palm csv
1703 #define PALM_CSV_NAME CSV_SPECIAL(0)
1704 #define PALM_CSV_END CSV_SPECIAL(1)
1705 #define PALM_CSV_CAT CSV_SPECIAL(2)
1707 static void
1708 palm_split_and_write_name(FILE *out, char *name)
1710 char *p;
1712 assert(name);
1714 if ( (p = strchr(name, ' ')) ) {
1716 * last name first
1718 fprintf(out, "\"%s\",\"" , p + 1);
1719 fwrite((void *)name, p - name, sizeof(char), out);
1720 fputc('\"', out);
1721 } else {
1722 fprintf(out, "\"%s\"", safe_str(name));
1726 static void
1727 palm_csv_handle_specials(FILE *out, int item, int field)
1729 switch(field) {
1730 case PALM_CSV_NAME:
1731 palm_split_and_write_name(out, db_name_get(item));
1732 break;
1733 case PALM_CSV_CAT:
1734 fprintf(out, "\"abook\"");
1735 break;
1736 case PALM_CSV_END:
1737 fprintf(out, "\"0\"");
1738 break;
1739 default:
1740 assert(0);
1744 static int
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 */
1753 FAX, /* FAX */
1754 MOBILEPHONE, /* OTHER */
1755 EMAIL, /* EMAIL */
1756 ADDRESS, /* ADDRESS */
1757 CITY, /* CITY */
1758 STATE, /* STATE */
1759 ZIP, /* ZIP */
1760 COUNTRY, /* COUNTRY */
1761 NICK, /* DEFINED 1 */
1762 URL, /* DEFINED 2 */
1763 CSV_UNDEFINED, /* DEFINED 3 */
1764 CSV_UNDEFINED, /* DEFINED 4 */
1765 NOTES, /* NOTE */
1766 PALM_CSV_END, /* "0" */
1767 PALM_CSV_CAT, /* CATEGORY */
1768 CSV_LAST
1771 csv_export_common(out, e, palm_export_fields, palm_csv_handle_specials);
1773 return 0;
1777 * end of csv export filters
1781 * GnomeCard (VCard) addressbook export filter
1784 static int
1785 gcrd_export_database(FILE *out, struct db_enumerator e)
1787 int j;
1788 char *name, *tmp;
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] == ' ')
1798 break;
1800 fprintf(out, "N:%s;%.*s\r\n",
1801 safe_str(name),
1803 safe_str(db_name_get(e.item))
1806 free(name);
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);
1832 if(*tmp) {
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);
1840 free(tmp);
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");
1853 return 0;
1857 * end of GnomeCard export filter
1862 * mutt alias export filter
1865 static char *
1866 mutt_alias_genalias(int i)
1868 char *tmp, *pos;
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, ' ') ) )
1876 *pos = 0;
1878 strlower(tmp);
1880 return tmp;
1883 static int
1884 mutt_alias_export(FILE *out, struct db_enumerator e)
1886 char email[MAX_EMAIL_LEN];
1887 char *alias = NULL;
1889 db_enumerate_items(e) {
1890 alias = mutt_alias_genalias(e.item);
1891 get_first_email(email, e.item);
1892 fprintf(out, *email ? "alias %s %s <%s>\n": "alias %s %s%s\n",
1893 alias,
1894 db_name_get(e.item),
1895 email);
1896 xfree(alias);
1899 return 0;
1903 * end of mutt alias export filter
1908 * printable export filter
1912 static void
1913 text_write_address_us(FILE *out, int i) {
1914 fprintf(out, "\n%s", db_fget(i, ADDRESS));
1916 if(db_fget(i, ADDRESS2))
1917 fprintf(out, "\n%s", db_fget(i, ADDRESS2));
1919 if(db_fget(i, CITY))
1920 fprintf(out, "\n%s", db_fget(i, CITY));
1922 if(db_fget(i, STATE) || db_fget(i, ZIP)) {
1923 fputc('\n', out);
1925 if(db_fget(i, STATE)) {
1926 fprintf(out, "%s", db_fget(i, STATE));
1927 if(db_fget(i, ZIP))
1928 fputc(' ', out);
1931 if(db_fget(i, ZIP))
1932 fprintf(out, "%s", db_fget(i, ZIP));
1935 if(db_fget(i, COUNTRY))
1936 fprintf(out, "\n%s", db_fget(i, COUNTRY));
1940 static void
1941 text_write_address_uk(FILE *out, int i) {
1942 int j;
1944 for(j = ADDRESS; j <= COUNTRY; j++)
1945 if(db_fget(i, j))
1946 fprintf(out, "\n%s", db_fget(i, j));
1949 static void
1950 text_write_address_eu(FILE *out, int i) {
1951 fprintf(out, "\n%s", db_fget(i, ADDRESS));
1953 if(db_fget(i, ADDRESS2))
1954 fprintf(out, "\n%s", db_fget(i, ADDRESS2));
1956 if(db_fget(i, ZIP) || db_fget(i, CITY)) {
1957 fputc('\n', out);
1959 if(db_fget(i, ZIP)) {
1960 fprintf(out, "%s", db_fget(i, ZIP));
1961 if(db_fget(i, CITY))
1962 fputc(' ', out);
1965 fprintf(out, "%s", safe_str(db_fget(i, CITY)));
1968 if(db_fget(i, STATE))
1969 fprintf(out, "\n%s", db_fget(i, STATE));
1971 if(db_fget(i, COUNTRY))
1972 fprintf(out, "\n%s", db_fget(i, COUNTRY));
1975 static int
1976 text_export_database(FILE * out, struct db_enumerator e)
1978 abook_list *emails, *em;
1979 int j;
1980 char *realname = get_real_name(), *str = NULL, *tmp;
1981 char *style = opt_get_str(STR_ADDRESS_STYLE);
1983 fprintf(out,
1984 "-----------------------------------------\n%s's address book\n"
1985 "-----------------------------------------\n\n\n",
1986 realname);
1987 free(realname);
1989 db_enumerate_items(e) {
1990 fprintf(out,
1991 "-----------------------------------------\n\n");
1992 fprintf(out, "%s", db_name_get(e.item));
1993 if(db_fget(e.item, NICK) && *db_fget(e.item, NICK))
1994 fprintf(out, "\n(%s)", db_fget(e.item, NICK));
1995 fprintf(out, "\n");
1997 tmp = db_email_get(e.item);
1998 if(*tmp) {
1999 emails = csv_to_abook_list(tmp);
2001 fprintf(out, "\n");
2002 for(em = emails; em; em = em->next)
2003 fprintf(out, "%s\n", em->data);
2005 abook_list_free(&emails);
2007 free(tmp);
2008 /* Print address */
2009 if(db_fget(e.item, ADDRESS)) {
2010 if(!safe_strcmp(style, "us")) /* US like */
2011 text_write_address_us(out, e.item);
2012 else if(!safe_strcmp(style, "uk")) /* UK like */
2013 text_write_address_uk(out, e.item);
2014 else /* EU like */
2015 text_write_address_eu(out, e.item);
2017 fprintf(out, "\n");
2020 if((db_fget(e.item, PHONE)) ||
2021 (db_fget(e.item, WORKPHONE)) ||
2022 (db_fget(e.item, FAX)) ||
2023 (db_fget(e.item, MOBILEPHONE))) {
2024 fprintf(out, "\n");
2025 for(j = PHONE; j <= MOBILEPHONE; j++)
2026 if(db_fget(e.item, j)) {
2027 get_field_info(field_id(j),
2028 NULL, &str, NULL);
2029 fprintf(out, "%s: %s\n", str,
2030 db_fget(e.item, j));
2034 if(db_fget(e.item, URL))
2035 fprintf(out, "\n%s\n", db_fget(e.item, URL));
2036 if(db_fget(e.item, NOTES))
2037 fprintf(out, "\n%s\n", db_fget(e.item, NOTES));
2039 fprintf(out, "\n");
2042 fprintf(out, "-----------------------------------------\n");
2044 return 0;
2048 * end of printable export filter
2052 * elm alias export filter
2055 static int
2056 elm_alias_export(FILE *out, struct db_enumerator e)
2058 char email[MAX_EMAIL_LEN];
2059 char *alias = NULL;
2061 db_enumerate_items(e) {
2062 alias = mutt_alias_genalias(e.item);
2063 get_first_email(email, e.item);
2064 fprintf(out, "%s = %s = %s\n",alias,db_name_get(e.item),email);
2065 xfree(alias);
2068 return 0;
2072 * end of elm alias export filter
2077 * Spruce export filter
2080 static int
2081 spruce_export_database (FILE *out, struct db_enumerator e)
2083 char email[MAX_EMAIL_LEN];
2085 fprintf(out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
2087 db_enumerate_items(e) {
2088 get_first_email(email, e.item);
2089 if(strcmp(email, "")) {
2090 fprintf(out, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
2091 e.item,
2092 db_name_get(e.item),
2093 email,
2094 safe_str(db_fget(e.item, NOTES))
2099 fprintf (out, "# End of address book file.\n");
2101 return 0;
2105 * end of Spruce export filter
2109 * wanderlust addressbook export filter
2112 static int
2113 wl_export_database(FILE *out, struct db_enumerator e)
2115 char email[MAX_EMAIL_LEN];
2117 fprintf(out, "# Wanderlust address book written by %s\n\n", PACKAGE);
2118 db_enumerate_items(e) {
2119 get_first_email(email, e.item);
2120 if(*email) {
2121 fprintf(out,
2122 "%s\t\"%s\"\t\"%s\"\n",
2123 email,
2124 safe_str(db_fget(e.item, NICK)),
2125 safe_str(db_name_get(e.item))
2130 fprintf (out, "\n# End of address book file.\n");
2132 return 0;
2136 * end of wanderlust addressbook export filter
2140 * BSD calendar export filter
2143 static int
2144 bsdcal_export_database(FILE *out, struct db_enumerator e)
2146 db_enumerate_items(e) {
2147 int year, month = 0, day = 0;
2148 char *anniversary = db_fget(e.item, ANNIVERSARY);
2150 if(anniversary) {
2151 parse_date_string(anniversary, &day, &month, &year);
2153 fprintf(out,
2154 _("%02d/%02d\tAnniversary of %s\n"),
2155 month,
2156 day,
2157 safe_str(db_name_get(e.item))
2162 return 0;
2166 * end of BSD calendar export filter