]> git.deb.at Git - pkg/abook.git/blob - filter.c
Merge branch 'dh'
[pkg/abook.git] / filter.c
1
2 /*
3  * $Id: filter.c,v 1.55 2006/09/06 02:46:44 cduval Exp $
4  *
5  * by JH <jheinonen@users.sourceforge.net>
6  *
7  * Copyright (C) Jaakko Heinonen
8  */
9
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>
29
30 extern abook_field_list *fields_list;
31 extern int fields_count;
32
33 /*
34  * function declarations
35  */
36
37 /*
38  * import filter prototypes
39  */
40
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
48 /*
49  * export filter prototypes
50  */
51
52 static int      ldif_export_database(FILE *out, struct db_enumerator e);
53 static int      html_export_database(FILE *out, struct db_enumerator e);
54 static int      pine_export_database(FILE *out, struct db_enumerator e);
55 static int      csv_export_database(FILE *out, struct db_enumerator e);
56 static int      allcsv_export_database(FILE *out, struct db_enumerator e);
57 static int      palm_export_database(FILE *out, struct db_enumerator e);
58 static int      gcrd_export_database(FILE *out, struct db_enumerator e);
59 static int      mutt_alias_export(FILE *out, struct db_enumerator e);
60 static int      elm_alias_export(FILE *out, struct db_enumerator e);
61 static int      text_export_database(FILE *out, struct db_enumerator e);
62 static int      spruce_export_database(FILE *out, struct db_enumerator e);
63 static int      wl_export_database(FILE *out, struct db_enumerator e);
64 static int      bsdcal_export_database(FILE *out, struct db_enumerator e);
65
66 /*
67  * end of function declarations
68  */
69
70 struct abook_input_filter i_filters[] = {
71         { "abook", N_("abook native format"), parse_database },
72         { "ldif", N_("ldif / Netscape addressbook"), ldif_parse_file },
73         { "mutt", N_("mutt alias"), mutt_parse_file },
74         { "pine", N_("pine addressbook"), pine_parse_file },
75         { "csv", N_("comma separated values"), csv_parse_file },
76         { "allcsv", N_("comma separated values (all fields)"), allcsv_parse_file },
77         { "palmcsv", N_("Palm comma separated values"), palmcsv_parse_file },
78         { "\0", NULL, NULL }
79 };
80
81 struct abook_output_filter e_filters[] = {
82         { "abook", N_("abook native format"), write_database },
83         { "ldif", N_("ldif / Netscape addressbook (.4ld)"), ldif_export_database },
84         { "mutt", N_("mutt alias"), mutt_alias_export },
85         { "html", N_("html document"), html_export_database },
86         { "pine", N_("pine addressbook"), pine_export_database },
87         { "gcrd", N_("GnomeCard (VCard) addressbook"), gcrd_export_database },
88         { "csv", N_("comma separated values"), csv_export_database },
89         { "allcsv", N_("comma separated values (all fields)"), allcsv_export_database },
90         { "palmcsv", N_("Palm comma separated values"), palm_export_database},
91         { "elm", N_("elm alias"), elm_alias_export },
92         { "text", N_("plain text"), text_export_database },
93         { "wl", N_("Wanderlust address book"), wl_export_database },
94         { "spruce", N_("Spruce address book"), spruce_export_database },
95         { "bsdcal", N_("BSD calendar"), bsdcal_export_database },
96         { "\0", NULL, NULL }
97 };
98
99 /*
100  * common functions
101  */
102
103 void
104 print_filters()
105 {
106         int i;
107
108         puts(_("input:"));
109         for(i=0; *i_filters[i].filtname ; i++)
110                 printf("\t%s\t%s\n", i_filters[i].filtname,
111                         gettext(i_filters[i].desc));
112
113         putchar('\n');
114
115         puts(_("output:"));
116         for(i=0; *e_filters[i].filtname ; i++)
117                 printf("\t%s\t%s\n", e_filters[i].filtname,
118                         gettext(e_filters[i].desc));
119
120         putchar('\n');
121 }
122
123 static int
124 number_of_output_filters()
125 {
126         int i;
127
128         for(i=0; *e_filters[i].filtname ; i++)
129                 ;
130
131         return i;
132 }
133
134 static int
135 number_of_input_filters()
136 {
137         int i;
138
139         for(i=0; *i_filters[i].filtname ; i++)
140                 ;
141
142         return i;
143 }
144
145 static char *
146 get_real_name()
147 {
148         char *username = getenv("USER");
149         struct passwd *pwent;
150         int rtn;
151         char *tmp;
152
153         pwent = getpwnam(username);
154
155         if((tmp = xstrdup(pwent->pw_gecos)) == NULL)
156                 return xstrdup(username);
157
158         rtn = sscanf(pwent->pw_gecos, "%[^,]", tmp);
159         if (rtn == EOF || rtn == 0) {
160                 free(tmp);
161                 return xstrdup(username);
162         } else
163                 return tmp;
164 }
165
166 /*
167  * import
168  */
169
170 static int              i_read_file(char *filename, int (*func) (FILE *in));
171
172 static void
173 import_screen()
174 {
175         int i;
176
177         clear();
178
179         refresh_statusline();
180         headerline(_("import database"));
181
182         mvaddstr(3, 1, _("please select a filter"));
183
184
185         for(i=0; *i_filters[i].filtname ; i++)
186                 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
187                         i_filters[i].filtname,
188                         gettext(i_filters[i].desc));
189
190         mvprintw(6 + i, 6, _("x -\tcancel"));
191 }
192
193 int
194 import_database()
195 {
196         int filter;
197         char *filename;
198         int tmp = db_n_items();
199
200         import_screen();
201
202         filter = getch() - 'a';
203         if(filter == 'x' - 'a' ||
204                 filter >= number_of_input_filters() || filter < 0) {
205                 refresh_screen();
206                 return 1;
207         }
208
209         mvaddstr(5+filter, 2, "->");
210
211         filename = ask_filename(_("Filename: "));
212         if(!filename) {
213                 refresh_screen();
214                 return 2;
215         }
216
217         if(i_read_file(filename, i_filters[filter].func ))
218                 statusline_msg(_("Error occured while opening the file"));
219         else if(tmp == db_n_items())
220                 statusline_msg(_("File does not seem to be a valid addressbook"));
221
222         refresh_screen();
223         free(filename);
224
225         return 0;
226 }
227
228
229
230 static int
231 i_read_file(char *filename, int (*func) (FILE *in))
232 {
233         FILE *in;
234         int ret = 0;
235
236         if( (in = abook_fopen( filename, "r" )) == NULL )
237                 return 1;
238
239         ret = (*func) (in);
240
241         fclose(in);
242
243         return ret;
244 }
245
246 int
247 import_file(char filtname[FILTNAME_LEN], char *filename)
248 {
249         int i;
250         int tmp = db_n_items();
251         int ret = 0;
252
253         for(i=0;; i++) {
254                 if(! strncasecmp(i_filters[i].filtname, filtname,
255                                         FILTNAME_LEN) )
256                         break;
257                 if(! *i_filters[i].filtname) {
258                         i = -1;
259                         break;
260                 }
261         }
262
263         if(i < 0)
264                 return -1;
265
266         if(!strcmp(filename, "-")) {
267                 struct stat s;
268                 if((fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode))
269                         ret = 1;
270                 else
271                         ret = (*i_filters[i].func) (stdin);
272         } else
273                 ret =  i_read_file(filename, i_filters[i].func);
274
275         if(tmp == db_n_items())
276                 ret = 1;
277
278         return ret;
279 }
280
281 /*
282  * export
283  */
284
285 static int e_write_file(char *filename,
286                 int (*func) (FILE *in, struct db_enumerator e), int mode);
287
288 static void
289 export_screen()
290 {
291         int i;
292
293         clear();
294
295
296         refresh_statusline();
297         headerline(_("export database"));
298
299         mvaddstr(3, 1, _("please select a filter"));
300
301
302         for(i = 0; *e_filters[i].filtname ; i++)
303                 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
304                         e_filters[i].filtname,
305                         gettext(e_filters[i].desc));
306
307         mvprintw(6 + i, 6, _("x -\tcancel"));
308 }
309
310 int
311 export_database()
312 {
313         int filter;
314         int enum_mode = ENUM_ALL;
315         char *filename;
316
317         export_screen();
318
319         filter = getch() - 'a';
320         if(filter == 'x' - 'a' ||
321                 filter >= number_of_output_filters() || filter < 0) {
322                 refresh_screen();
323                 return 1;
324         }
325
326         mvaddstr(5 + filter, 2, "->");
327
328         if(selected_items()) {
329                 switch(statusline_askchoice(
330                         _("Export <a>ll, export <s>elected, or <c>ancel?"),
331                         S_("keybindings:all/selected/cancel|asc"), 3)) {
332                         case 1:
333                                 break;
334                         case 2:
335                                 enum_mode = ENUM_SELECTED;
336                                 break;
337                         case 0:
338                         case 3:
339                                 refresh_screen();
340                                 return 1;
341                 }
342                 clear_statusline();
343         }
344
345         filename = ask_filename(_("Filename: "));
346         if(!filename) {
347                 refresh_screen();
348                 return 2;
349         }
350
351         if( e_write_file(filename, e_filters[filter].func, enum_mode))
352                 statusline_msg(_("Error occured while exporting"));
353
354         refresh_screen();
355         free(filename);
356
357         return 0;
358 }
359
360 static int
361 e_write_file(char *filename, int (*func) (FILE *in, struct db_enumerator e),
362                 int mode)
363 {
364         FILE *out;
365         int ret = 0;
366         struct db_enumerator enumerator = init_db_enumerator(mode);
367
368         if((out = fopen(filename, "a")) == NULL)
369                 return 1;
370
371         if(ftell(out))
372                 return 1;
373
374         ret = (*func) (out, enumerator);
375
376         fclose(out);
377
378         return ret;
379 }
380
381 int
382 fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode)
383 {
384         int i;
385         struct db_enumerator e = init_db_enumerator(enum_mode);
386
387         for(i=0;; i++) {
388                 if(!strncasecmp(e_filters[i].filtname, filtname,
389                                         FILTNAME_LEN))
390                         break;
391                 if(!*e_filters[i].filtname) {
392                         i = -1;
393                         break;
394                 }
395         }
396
397         return (e_filters[i].func) (handle, e);
398 }
399
400
401
402 int
403 export_file(char filtname[FILTNAME_LEN], char *filename)
404 {
405         const int mode = ENUM_ALL;
406         int i;
407         int ret = 0;
408         struct db_enumerator e = init_db_enumerator(mode);
409
410         for(i=0;; i++) {
411                 if(!strncasecmp(e_filters[i].filtname, filtname,
412                                         FILTNAME_LEN))
413                         break;
414                 if(!*e_filters[i].filtname) {
415                         i = -1;
416                         break;
417                 }
418         }
419
420         if(i < 0)
421                 return -1;
422
423         if(!strcmp(filename, "-"))
424                 ret = (e_filters[i].func) (stdout, e);
425         else
426                 ret =  e_write_file(filename, e_filters[i].func, mode);
427
428         return ret;
429 }
430
431 /*
432  * end of common functions
433  */
434
435 /*
436  * ldif import
437  */
438
439 #include "ldif.h"
440
441 static void     ldif_fix_string(char *str);
442
443 #define LDIF_ITEM_FIELDS        16
444
445 typedef char *ldif_item[LDIF_ITEM_FIELDS];
446
447 static ldif_item ldif_field_names = {
448         "cn",
449         "mail",
450         "streetaddress",
451         "streetaddress2",
452         "locality",
453         "st",
454         "postalcode",
455         "countryname",
456         "homephone",
457         "description",
458         "homeurl",
459         "facsimiletelephonenumber",
460         "cellphone",
461         "xmozillaanyphone",
462         "xmozillanickname",
463         "objectclass", /* this must be the last entry */
464 };
465
466 static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
467         NAME,           /* "cn" */
468         EMAIL,          /* "mail" */
469         ADDRESS,        /* "streetaddress" */
470         ADDRESS2,       /* "streetaddress2" */
471         CITY,           /* "locality" */
472         STATE,          /* "st" */
473         ZIP,            /* "postalcode" */
474         COUNTRY,        /* "countryname" */
475         PHONE,          /* "homephone" */
476         NOTES,          /* "description" */
477         URL,            /* "homeurl" */
478         FAX,            /* "facsimiletelephonenumber" */
479         MOBILEPHONE,    /* "cellphone" */
480         WORKPHONE,      /* "xmozillaanyphone" */
481         NICK,           /* "xmozillanickname" */
482         -1,             /* "objectclass" */ /* this must be the last entry */
483 };
484
485
486 static char *
487 ldif_read_line(FILE *in)
488 {
489         char *buf = NULL;
490         char *ptr, *tmp;
491         long pos;
492         int i;
493
494         for(i = 1;;i++) {
495                 char *line;
496
497                 pos = ftell(in);
498                 line = getaline(in);
499
500                 if(feof(in) || !line)
501                         break;
502
503                 if(i == 1) {
504                         buf = line;
505                         continue;
506                 }
507
508                 if(*line != ' ') {
509                         fseek(in, pos, SEEK_SET); /* fixme ! */
510                         free(line);
511                         break;
512                 }
513
514                 ptr = line;
515                 while( *ptr == ' ')
516                         ptr++;
517
518                 tmp = buf;
519                 buf = strconcat(buf, ptr, NULL);
520                 free(tmp);
521                 free(line);
522         }
523
524         if(buf && *buf == '#' ) {
525                 free(buf);
526                 return NULL;
527         }
528
529         return buf;
530 }
531
532 static void
533 ldif_add_item(ldif_item li)
534 {
535         list_item item;
536         int i;
537
538         item = item_create();
539
540         if(!li[LDIF_ITEM_FIELDS -1])
541                 goto bail_out;
542
543
544         for(i=0; i < LDIF_ITEM_FIELDS; i++) {
545                 if(ldif_conv_table[i] >= 0 && li[i] && *li[i])
546                         item_fput(item,ldif_conv_table[i],xstrdup(li[i]));
547         }
548
549         add_item2database(item);
550
551 bail_out:
552         for(i=0; i < LDIF_ITEM_FIELDS; i++)
553                 xfree(li[i]);
554         item_free(&item);
555
556 }
557
558 static void
559 ldif_convert(ldif_item item, char *type, char *value)
560 {
561         int i;
562
563         if(!strcmp(type, "dn")) {
564                 ldif_add_item(item);
565                 return;
566         }
567
568         for(i=0; i < LDIF_ITEM_FIELDS; i++) {
569                 if(!safe_strcmp(ldif_field_names[i], type) && *value) {
570                         if(i == LDIF_ITEM_FIELDS - 1) /* this is a dirty hack */
571                                 if(safe_strcmp("person", value))
572                                         break;
573
574                         if(item_fget(item, i))
575                                 free(item_fget(item, i));
576
577                         item_fput(item, i, xstrdup(value));
578                 }
579         }
580 }
581
582 static int
583 ldif_parse_file(FILE *handle)
584 {
585         char *line = NULL;
586         char *type, *value;
587         int vlen;
588         ldif_item item;
589
590         memset(item, 0, sizeof(item));
591
592         do {
593                 if( !(line = ldif_read_line(handle)) )
594                         continue;
595
596                 if(-1 == (str_parse_line(line, &type, &value, &vlen))) {
597                         xfree(line);
598                         continue; /* just skip the errors */
599                 }
600
601                 ldif_fix_string(value);
602
603                 ldif_convert(item, type, value);
604
605                 xfree(line);
606         } while ( !feof(handle) );
607
608         ldif_convert(item, "dn", "");
609
610         return 0;
611 }
612
613 static void
614 ldif_fix_string(char *str)
615 {
616         int i, j;
617
618         for(i = 0, j = 0; j < (int)strlen(str); i++, j++)
619                 str[i] = ( str[j] == (char)0xc3 ?
620                                 (char) str[++j] + (char) 0x40 :
621                                 str[j] );
622
623         str[i] = 0;
624 }
625
626 /*
627  * end of ldif import
628  */
629
630 /*
631  * mutt alias import filter
632  */
633
634 #include "getname.h"
635
636 static int
637 mutt_read_line(FILE *in, char **alias, char **rest)
638 {
639         char *line, *ptr, *tmp;
640         size_t alias_len;
641
642         if( !(line = ptr = getaline(in)) )
643                 return 1; /* error / EOF */
644
645         SKIPWS(ptr);
646
647         if(strncmp("alias", ptr, 5)) {
648                 free(line);
649                 return 1;
650         }
651
652         ptr += 5;
653
654         SKIPWS(ptr);
655
656         tmp = ptr;
657
658         while( ! ISSPACE(*ptr) )
659                 ptr++;
660
661         alias_len = (size_t)(ptr - tmp);
662
663         if(alias)
664                 *alias = xmalloc_inc(alias_len, 1);
665
666         strncpy(*alias, tmp, alias_len);
667         *(*alias + alias_len) = 0;
668
669         SKIPWS(ptr);
670
671         *rest = xstrdup(ptr);
672
673         free(line);
674         return 0;
675 }
676
677 static void
678 mutt_fix_quoting(char *p)
679 {
680         char *escape = 0;
681
682         for(; *p; p++) {
683                 switch(*p) {
684                         case '\"':
685                                 if(escape)
686                                         *escape = ' ';
687                                 break;
688                         case '\\':
689                                 escape = p;
690                                 break;
691                         default:
692                                 escape = 0;
693                 }
694         }
695 }
696
697 static void
698 mutt_parse_email(list_item item)
699 {
700         char *line = item_fget(item, NAME);
701         char *tmp;
702         char *name, *email;
703 #if 0
704         char *start = line;
705         int i = 0;
706 #endif
707
708         mutt_fix_quoting(line);
709         tmp = strconcat("From: ", line, NULL);
710         getname(tmp, &name, &email);
711         free(tmp);
712
713         if(name)
714                 item_fput(item, NAME, name);
715         else
716                 return;
717
718         if(email)
719                 item_fput(item, EMAIL, email);
720         else
721                 return;
722
723         /*
724          * this is completely broken
725          */
726 #if 0
727         while( (start = strchr(start, ',')) && i++ < MAX_EMAILS - 1) {
728                 tmp = strconcat("From: ", ++start, NULL);
729                 getname(tmp, &name, &email);
730                 free(tmp);
731                 free(name);
732                 if(email) {
733                         if(*email) {
734                                 tmp = strconcat(item[EMAIL], ",", email, NULL);
735                                 free(item[EMAIL]);
736                                 item[EMAIL] = tmp;
737                         } else {
738                                 xfree(email);
739                         }
740                 }
741         }
742 #endif
743 }
744
745 static int
746 mutt_parse_file(FILE *in)
747 {
748         list_item item = item_create();
749
750         for(;;) {
751                 memset(item, 0, fields_count * sizeof(char *));
752
753                 if(!mutt_read_line(in,
754                                         (field_id(NICK) != -1) ?
755                                         &item[field_id(NICK)] : NULL,
756                                         &item[field_id(NAME)]))
757                         mutt_parse_email(item);
758
759                 if(feof(in)) {
760                         item_empty(item);
761                         break;
762                 }
763
764                 add_item2database(item);
765         }
766         item_free(&item);
767
768         return 0;
769 }
770
771 /*
772  * end of mutt alias import filter
773  */
774
775
776 /*
777  * ldif export filter
778  */
779
780 static void
781 ldif_fput_type_and_value(FILE *out,char *type, char *value )
782 {
783         char *tmp;
784
785         tmp = ldif_type_and_value(type, value, strlen(value));
786
787         fputs(tmp, out);
788
789         free(tmp);
790 }
791
792 static int
793 ldif_export_database(FILE *out, struct db_enumerator e)
794 {
795         char email[MAX_EMAILSTR_LEN];
796
797         fprintf(out, "version: 1\n");
798
799         db_enumerate_items(e) {
800                 char *tmp;
801                 int j;
802                 get_first_email(email, e.item);
803
804                 tmp = strdup_printf("cn=%s,mail=%s",db_name_get(e.item),email);
805
806                 ldif_fput_type_and_value(out, "dn", tmp);
807                 free(tmp);
808
809                 for(j = 0; j < LDIF_ITEM_FIELDS; j++) {
810                         if(ldif_conv_table[j] >= 0) {
811                                 if(ldif_conv_table[j] == EMAIL)
812                                         ldif_fput_type_and_value(out,
813                                                 ldif_field_names[j], email);
814                                 else if(db_fget(e.item,ldif_conv_table[j]))
815                                         ldif_fput_type_and_value(out,
816                                                 ldif_field_names[j],
817                                                 db_fget(e.item,
818                                                         ldif_conv_table[j]));
819                         }
820                 }
821
822                 fprintf(out, "objectclass: top\n"
823                                 "objectclass: person\n\n");
824         }
825
826         return 0;
827 }
828
829 /*
830  * end of ldif export filter
831  */
832
833 /*
834  * html export filter
835  */
836
837 static void            html_export_write_head(FILE *out);
838 static void            html_export_write_tail(FILE *out);
839
840 extern struct index_elem *index_elements;
841
842 static void
843 html_print_emails(FILE *out, struct list_field *f)
844 {
845         abook_list *l = csv_to_abook_list(f->data);
846
847         for(; l; l = l->next) {
848                 fprintf(out, "<a href=\"mailto:%s\">%s</a>", l->data, l->data);
849                 if(l->next)
850                         fprintf(out, ", ");
851         }
852
853         abook_list_free(&l);
854 }
855
856 static int
857 html_export_database(FILE *out, struct db_enumerator e)
858 {
859         struct list_field f;
860         struct index_elem *cur;
861
862         if(list_is_empty())
863                 return 2;
864
865         init_index();
866
867         html_export_write_head(out);
868
869         db_enumerate_items(e) {
870                 fprintf(out, "<tr>");
871                 for(cur = index_elements; cur; cur = cur->next) {
872                         if(cur->type != INDEX_FIELD)
873                                 continue;
874
875                         get_list_field(e.item, cur, &f);
876
877                         if(f.type == FIELD_EMAILS) {
878                                 fprintf(out, "<td>");
879                                 html_print_emails(out, &f);
880                                 fprintf(out, "</td>");
881                                 continue;
882                         } else {
883                                 fprintf(out, "<td>%s</td>", safe_str(f.data));
884                         }
885                 }
886                 fprintf(out, "</tr>\n");
887         }
888
889         html_export_write_tail(out);
890
891         return 0;
892 }
893
894 static void
895 html_export_write_head(FILE *out)
896 {
897         char *realname = get_real_name(), *str;
898         struct index_elem *cur;
899
900         fprintf(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
901         fprintf(out, "<html>\n<head>\n <title>%s's addressbook</title>",
902                         realname );
903         fprintf(out, "\n</head>\n<body>\n");
904         fprintf(out, "\n<h2>%s's addressbook</h2>\n", realname );
905         fprintf(out, "<br><br>\n\n");
906
907         fprintf(out, "<table border=\"1\" align=\"center\">\n<tr>");
908         for(cur = index_elements; cur; cur = cur->next) {
909                 if(cur->type != INDEX_FIELD)
910                         continue;
911
912                 get_field_info(cur->d.field.id, NULL, &str, NULL);
913                 fprintf(out, "<th>%s</th>", str);
914         }
915         fprintf(out, "</tr>\n\n");
916
917         free(realname);
918 }
919
920 static void
921 html_export_write_tail(FILE *out)
922 {
923         fprintf(out, "\n</table>\n");
924         fprintf(out, "\n</body>\n</html>\n");
925 }
926
927 /*
928  * end of html export filter
929  */
930
931
932 /*
933  * pine addressbook import filter
934  */
935
936 #define PINE_BUF_SIZE 2048
937
938 static void
939 pine_fixbuf(char *buf)
940 {
941         int i,j;
942
943         for(i = 0,j = 0; j < (int)strlen(buf); i++, j++)
944                 buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
945 }
946
947 static void
948 pine_convert_emails(char *s)
949 {
950         int i;
951         char *tmp;
952
953         if(s == NULL || *s != '(')
954                 return;
955
956         for(i = 0; s[i]; i++)
957                 s[i] = s[i + 1];
958
959         if( ( tmp = strchr(s,')')) )
960                 *tmp = '\0';
961
962         for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
963                 if(i > MAX_LIST_ITEMS - 1) {
964                         *tmp = '\0';
965                         break;
966                 }
967
968 }
969
970 static void
971 pine_parse_buf(char *buf)
972 {
973         list_item item;
974         char *start = buf;
975         char *end;
976         char tmp[PINE_BUF_SIZE];
977         int i, len, last;
978         int pine_conv_table[]= {NICK, NAME, EMAIL, -1, NOTES};
979
980         item = item_create();
981
982         for(i=0, last=0; !last ; i++) {
983                 if( !(end = strchr(start, '\t')) )
984                         last=1;
985
986                 len = last ? strlen(start) : (int) (end-start);
987                 len = min(len, PINE_BUF_SIZE - 1);
988
989                 if(i < (int)(sizeof(pine_conv_table) / sizeof(*pine_conv_table))
990                                 && pine_conv_table[i] >= 0) {
991                         strncpy(tmp, start, len);
992                         tmp[len] = 0;
993                         if(*tmp)
994                                 item_fput(item, pine_conv_table[i],
995                                                 xstrdup(tmp));
996                 }
997                 start = end + 1;
998         }
999
1000         pine_convert_emails(item_fget(item, EMAIL));
1001         add_item2database(item);
1002         item_free(&item);
1003 }
1004
1005
1006 #define LINESIZE        1024
1007
1008 static int
1009 pine_parse_file(FILE *in)
1010 {
1011         char line[LINESIZE];
1012         char *buf = NULL;
1013         char *ptr;
1014         int i;
1015
1016         fgets(line, LINESIZE, in);
1017
1018         while(!feof(in)) {
1019                 for(i = 2;;i++) {
1020                         buf = xrealloc(buf, i*LINESIZE);
1021                         if(i == 2)
1022                                 strcpy(buf, line);
1023                         fgets(line, LINESIZE, in);
1024                         ptr=(char *)&line;
1025                         if(*ptr != ' ' || feof(in))
1026                                 break;
1027                         else
1028                                 while(*ptr == ' ')
1029                                         ptr++;
1030
1031                         strcat(buf, ptr);
1032                 }
1033                 if(*buf == '#') {
1034                         xfree(buf);
1035                         continue;
1036                 }
1037                 pine_fixbuf(buf);
1038
1039                 pine_parse_buf(buf);
1040
1041                 xfree(buf);
1042         }
1043
1044         return 0;
1045 }
1046
1047 /*
1048  * end of pine addressbook import filter
1049  */
1050
1051
1052 /*
1053  * pine addressbook export filter
1054  *
1055  *  filter doesn't wrap the lines as it should but Pine seems to handle
1056  *  created files without problems - JH
1057  */
1058
1059 static int
1060 pine_export_database(FILE *out, struct db_enumerator e)
1061 {
1062         char *emails;
1063
1064         db_enumerate_items(e) {
1065                 emails = db_email_get(e.item);
1066                 fprintf(out, strchr(emails, ',') /* multiple addresses? */ ?
1067                                 "%s\t%s\t(%s)\t\t%s\n" : "%s\t%s\t%s\t\t%s\n",
1068                                 safe_str(db_fget(e.item, NICK)),
1069                                 safe_str(db_name_get(e.item)),
1070                                 emails,
1071                                 safe_str(db_fget(e.item, NOTES))
1072                                 );
1073                 free(emails);
1074         }
1075
1076         return 0;
1077 }
1078
1079 /*
1080  * end of pine addressbook export filter
1081  */
1082
1083
1084 /*
1085  * csv import filter
1086  */
1087
1088 /* FIXME
1089  * these files should be parsed according to a certain
1090  * lay out, or the default if layout is not given, at
1091  * the moment only default is done...
1092  */
1093
1094 #define CSV_COMMENT_CHAR        '#'
1095 #define CSV_DUPLICATE_SEPARATOR " "
1096 #define CSV_TABLE_SIZE(t)       (sizeof (t) / sizeof *(t))
1097
1098 static int csv_conv_table[] = {
1099         NAME,
1100         EMAIL,
1101         PHONE,
1102         NOTES,
1103         NICK
1104 };
1105
1106 static int allcsv_conv_table[] = {
1107         NAME,
1108         EMAIL,
1109         ADDRESS,
1110         ADDRESS2,
1111         CITY,
1112         STATE,
1113         ZIP,
1114         COUNTRY,
1115         PHONE,
1116         WORKPHONE,
1117         FAX,
1118         MOBILEPHONE,
1119         NICK,
1120         URL,
1121         NOTES,
1122         ANNIVERSARY
1123 };
1124
1125 static int palmcsv_conv_table[] = {
1126         NAME,           /* Last name */
1127         NAME,           /* First name */
1128         NOTES,          /* Title */
1129         NICK,           /* Company */
1130         WORKPHONE,
1131         PHONE,
1132         FAX,
1133         MOBILEPHONE,
1134         EMAIL,
1135         ADDRESS,
1136         CITY,
1137         STATE,
1138         ZIP,
1139         COUNTRY,
1140         ANNIVERSARY,
1141 };
1142
1143 static void
1144 csv_convert_emails(char *s)
1145 {
1146         int i;
1147         char *tmp;
1148
1149         if(s == NULL)
1150                 return;
1151
1152         for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
1153                 if(i > MAX_LIST_ITEMS - 1) {
1154                         *tmp = 0;
1155                         break;
1156                 }
1157
1158 }
1159
1160 static char *
1161 csv_remove_quotes(char *s)
1162 {
1163         char *copy, *trimmed;
1164         int len;
1165
1166         copy = trimmed = xstrdup(s);
1167         strtrim(trimmed);
1168
1169         len = strlen(trimmed);
1170         if(trimmed[len - 1] == '\"' && *trimmed == '\"') {
1171                 if(len < 3) {
1172                         xfree(copy);
1173                         return NULL;
1174                 }
1175                 trimmed[len - 1] = 0;
1176                 trimmed++;
1177                 trimmed = xstrdup(trimmed);
1178                 free(copy);
1179                 return trimmed;
1180         }
1181
1182         xfree(copy);
1183         return xstrdup(s);
1184 }
1185
1186 static int
1187 csv_field_to_item(int *table_base, size_t table_size, int field)
1188 {
1189         if(field < table_size)
1190                 return field_id(table_base[field]);
1191
1192         return -1;
1193 }
1194
1195 static void
1196 csv_store_item(list_item item, int i, char *s)
1197 {
1198         char *newstr = NULL;
1199
1200         if(!s || !*s)
1201                 return;
1202
1203         if( !(newstr = csv_remove_quotes(s)) )
1204                 return;
1205
1206         if(i >= 0) {
1207                 if (item[i] != NULL) {
1208                         char *oldstr = item[i];
1209
1210                         item[i] = strconcat(newstr, CSV_DUPLICATE_SEPARATOR,
1211                                 oldstr, NULL);
1212                         xfree(newstr);
1213                         xfree(oldstr);
1214                 } else {
1215                         item[i] = newstr;
1216                 }
1217         } else {
1218                 xfree(newstr);
1219         }
1220 }
1221
1222 static int
1223 csv_is_valid_quote_end(char *p)
1224 {
1225         if(*p != '\"')
1226                 return FALSE;
1227
1228         for(p++; *p; p++) {
1229                 if(*p == ',')
1230                         return TRUE;
1231                 else if(!ISSPACE(*p))
1232                         return FALSE;
1233         }
1234
1235         return TRUE;
1236 }
1237
1238 static int
1239 csv_is_valid_quote_start(char *p)
1240 {
1241         for(; *p; p++) {
1242                 if(*p == '\"')
1243                         return TRUE;
1244                 else if(!ISSPACE(*p))
1245                         return FALSE;
1246         }
1247
1248         return FALSE;
1249 }
1250
1251 static void
1252 csv_parse_line(char *line, int *table_base, size_t table_size)
1253 {
1254         char *p, *start;
1255         int field;
1256         bool in_quote = FALSE;
1257         list_item item;
1258
1259         item = item_create();
1260
1261         for(p = start = line, field = 0; *p; p++) {
1262                 if(in_quote) {
1263                         if(csv_is_valid_quote_end(p))
1264                                 in_quote = FALSE;
1265                 } else {
1266                         if ( (((p - start) / sizeof (char)) < 2 ) &&
1267                                 csv_is_valid_quote_start(p) )
1268                                 in_quote = TRUE;
1269                 }
1270
1271                 if(*p == ',' && !in_quote) {
1272                         *p = 0;
1273                         csv_store_item(item,
1274                                 csv_field_to_item(table_base,table_size,field),
1275                                 start);
1276                         field++;
1277                         start = p + 1;
1278                 }
1279         }
1280         /*
1281          * store last field
1282          */
1283         csv_store_item(item, csv_field_to_item(table_base, table_size, field),
1284                 start);
1285
1286         csv_convert_emails(item_fget(item, EMAIL));
1287         add_item2database(item);
1288         item_free(&item);
1289 }
1290
1291 static int
1292 csv_parse_file_common(FILE *in, int *conv_table, size_t table_size)
1293 {
1294         char *line = NULL;
1295
1296         while(!feof(in)) {
1297                 line = getaline(in);
1298
1299                 if(line && *line && *line != CSV_COMMENT_CHAR)
1300                         csv_parse_line(line, conv_table, table_size);
1301
1302                 xfree(line);
1303         }
1304
1305         return 0;
1306 }
1307
1308 static int
1309 csv_parse_file(FILE *in)
1310 {
1311         return csv_parse_file_common(in, csv_conv_table,
1312                 CSV_TABLE_SIZE(csv_conv_table));
1313 }
1314
1315 static int
1316 allcsv_parse_file(FILE *in)
1317 {
1318         return csv_parse_file_common(in, allcsv_conv_table,
1319                 CSV_TABLE_SIZE(allcsv_conv_table));
1320 }
1321
1322 static int
1323 palmcsv_parse_file(FILE *in)
1324 {
1325         return csv_parse_file_common(in, palmcsv_conv_table,
1326                 CSV_TABLE_SIZE(palmcsv_conv_table));
1327 }
1328
1329 /*
1330  * end of csv import filter
1331  */
1332
1333 /*
1334  * csv addressbook export filters
1335  */
1336
1337 #define CSV_LAST                (-1)
1338 #define CSV_UNDEFINED           (-2)
1339 #define CSV_SPECIAL(X)          (-3 - (X))
1340 #define CSV_IS_SPECIAL(X)       ((X) <= -3)
1341
1342 static int
1343 csv_export_common(FILE *out, struct db_enumerator e,
1344                 int fields[], void (*special_func)(FILE *, int, int))
1345 {
1346         int i;
1347
1348         db_enumerate_items(e) {
1349                 for(i = 0; fields[i] != CSV_LAST; i++) {
1350                         if(fields[i] == CSV_UNDEFINED)
1351                                 fprintf(out, "\"\"");
1352                         else if(CSV_IS_SPECIAL(fields[i])) {
1353                                 if(special_func)
1354                                         (*special_func)(out, e.item, fields[i]);
1355                         } else
1356                                 /*fprintf(out,(
1357                         strchr(safe_str(database[e.item][field_idx(fields[i])]), ',') ||
1358                         strchr(safe_str(database[e.item][field_idx(fields[i])]), '\"')) ?
1359                                 "\"%s\"" : "%s",
1360                                 safe_str(database[e.item][field_idx(fields[i])])
1361                                 );*/
1362                                 fprintf(out, "\"%s\"",
1363                                         safe_str(db_fget(e.item,fields[i])));
1364
1365                         if(fields[i + 1] != CSV_LAST)
1366                                 fputc(',', out);
1367                 }
1368                 fputc('\n', out);
1369         }
1370
1371         return 0;
1372 }
1373
1374 static int
1375 csv_export_database(FILE *out, struct db_enumerator e)
1376 {
1377         int csv_export_fields[] = {
1378                 NAME,
1379                 EMAIL,
1380                 PHONE,
1381                 NOTES,
1382                 NICK,
1383                 CSV_LAST
1384         };
1385
1386         csv_export_common(out, e, csv_export_fields, NULL);
1387
1388         return 0;
1389 }
1390
1391 static int
1392 allcsv_export_database(FILE *out, struct db_enumerator e)
1393 {
1394         /*
1395          * TODO: Should get these atomatically from abook_fileds
1396          *  - JH
1397          */
1398         int allcsv_export_fields[] = {
1399                 NAME,
1400                 EMAIL,
1401                 ADDRESS,
1402                 ADDRESS2,
1403                 CITY,
1404                 STATE,
1405                 ZIP,
1406                 COUNTRY,
1407                 PHONE,
1408                 WORKPHONE,
1409                 FAX,
1410                 MOBILEPHONE,
1411                 NICK,
1412                 URL,
1413                 NOTES,
1414                 ANNIVERSARY,
1415                 CSV_LAST
1416         };
1417
1418         fprintf(out, "#");
1419         fprintf(out, "\"NAME\",");
1420         fprintf(out, "\"EMAIL\",");
1421         fprintf(out, "\"ADDRESS\",");
1422         fprintf(out, "\"ADDRESS2\",");
1423         fprintf(out, "\"CITY\",");
1424         fprintf(out, "\"STATE\",");
1425         fprintf(out, "\"ZIP\",");
1426         fprintf(out, "\"COUNTRY\",");
1427         fprintf(out, "\"PHONE\",");
1428         fprintf(out, "\"WORKPHONE\",");
1429         fprintf(out, "\"FAX\",");
1430         fprintf(out, "\"MOBILEPHONE\",");
1431         fprintf(out, "\"NICK\",");
1432         fprintf(out, "\"URL\",");
1433         fprintf(out, "\"NOTES\",");
1434         fprintf(out, "\"ANNIVERSARY\"\n");
1435
1436         csv_export_common(out, e, allcsv_export_fields, NULL);
1437
1438         return 0;
1439 }
1440
1441 /*
1442  * palm csv
1443  */
1444
1445 #define PALM_CSV_NAME   CSV_SPECIAL(0)
1446 #define PALM_CSV_END    CSV_SPECIAL(1)
1447 #define PALM_CSV_CAT    CSV_SPECIAL(2)
1448
1449 static void
1450 palm_split_and_write_name(FILE *out, char *name)
1451 {
1452         char *p;
1453
1454         assert(name);
1455
1456         if ( (p = strchr(name, ' ')) ) {
1457                 /*
1458                  * last name first
1459                  */
1460                 fprintf(out, "\"%s\",\"" , p + 1);
1461                 fwrite((void *)name, p - name, sizeof(char), out);
1462                 fputc('\"', out);
1463         } else {
1464                 fprintf(out, "\"%s\"", safe_str(name));
1465         }
1466 }
1467
1468 static void
1469 palm_csv_handle_specials(FILE *out, int item, int field)
1470 {
1471         switch(field) {
1472                 case PALM_CSV_NAME:
1473                         palm_split_and_write_name(out, db_name_get(item));
1474                         break;
1475                 case PALM_CSV_CAT:
1476                         fprintf(out, "\"abook\"");
1477                         break;
1478                 case PALM_CSV_END:
1479                         fprintf(out, "\"0\"");
1480                         break;
1481                 default:
1482                         assert(0);
1483         }
1484 }
1485
1486 static int
1487 palm_export_database(FILE *out, struct db_enumerator e)
1488 {
1489         int palm_export_fields[] = {
1490                 PALM_CSV_NAME,          /* LASTNAME, FIRSTNAME  */
1491                 CSV_UNDEFINED,          /* TITLE                */
1492                 CSV_UNDEFINED,          /* COMPANY              */
1493                 WORKPHONE,              /* WORK PHONE           */
1494                 PHONE,                  /* HOME PHONE           */
1495                 FAX,                    /* FAX                  */
1496                 MOBILEPHONE,            /* OTHER                */
1497                 EMAIL,                  /* EMAIL                */
1498                 ADDRESS,                /* ADDRESS              */
1499                 CITY,                   /* CITY                 */
1500                 STATE,                  /* STATE                */
1501                 ZIP,                    /* ZIP                  */
1502                 COUNTRY,                /* COUNTRY              */
1503                 NICK,                   /* DEFINED 1            */
1504                 URL,                    /* DEFINED 2            */
1505                 CSV_UNDEFINED,          /* DEFINED 3            */
1506                 CSV_UNDEFINED,          /* DEFINED 4            */
1507                 NOTES,                  /* NOTE                 */
1508                 PALM_CSV_END,           /* "0"                  */
1509                 PALM_CSV_CAT,           /* CATEGORY             */
1510                 CSV_LAST
1511         };
1512
1513         csv_export_common(out, e, palm_export_fields, palm_csv_handle_specials);
1514
1515         return 0;
1516 }
1517
1518 /*
1519  * end of csv export filters
1520  */
1521
1522 /*
1523  * GnomeCard (VCard) addressbook export filter
1524  */
1525
1526 static int
1527 gcrd_export_database(FILE *out, struct db_enumerator e)
1528 {
1529         int j;
1530         char *name, *tmp;
1531         abook_list *emails, *em;
1532
1533         db_enumerate_items(e) {
1534                 fprintf(out, "BEGIN:VCARD\r\nFN:%s\r\n",
1535                                 safe_str(db_name_get(e.item)));
1536
1537                 name = get_surname(db_name_get(e.item));
1538                 for( j = strlen(db_name_get(e.item)) - 1; j >= 0; j-- ) {
1539                         if((db_name_get(e.item))[j] == ' ')
1540                                 break;
1541                 }
1542                 fprintf(out, "N:%s;%.*s\r\n",
1543                         safe_str(name),
1544                         j,
1545                         safe_str(db_name_get(e.item))
1546                         );
1547
1548                 free(name);
1549
1550                 if(db_fget(e.item, ADDRESS))
1551                         fprintf(out, "ADR:;;%s;%s;%s;%s;%s;%s\r\n",
1552                                 safe_str(db_fget(e.item, ADDRESS)),
1553                                 safe_str(db_fget(e.item, ADDRESS2)),
1554                                 safe_str(db_fget(e.item, CITY)),
1555                                 safe_str(db_fget(e.item, STATE)),
1556                                 safe_str(db_fget(e.item, ZIP)),
1557                                 safe_str(db_fget(e.item, COUNTRY))
1558                                 );
1559
1560                 if(db_fget(e.item, PHONE))
1561                         fprintf(out, "TEL;HOME:%s\r\n",
1562                                         db_fget(e.item, PHONE));
1563                 if(db_fget(e.item, WORKPHONE))
1564                         fprintf(out, "TEL;WORK:%s\r\n",
1565                                         db_fget(e.item, WORKPHONE));
1566                 if(db_fget(e.item, FAX))
1567                         fprintf(out, "TEL;FAX:%s\r\n",
1568                                         db_fget(e.item, FAX));
1569                 if(db_fget(e.item, MOBILEPHONE))
1570                         fprintf(out, "TEL;CELL:%s\r\n",
1571                                         db_fget(e.item, MOBILEPHONE));
1572
1573                 tmp = db_email_get(e.item);
1574                 if(*tmp) {
1575                         emails = csv_to_abook_list(tmp);
1576
1577                         for(em = emails; em; em = em->next)
1578                                 fprintf(out, "EMAIL;INTERNET:%s\r\n", em->data);
1579
1580                         abook_list_free(&emails);
1581                 }
1582                 free(tmp);
1583
1584                 if(db_fget(e.item, NOTES))
1585                         fprintf(out, "NOTE:%s\r\n",
1586                                         db_fget(e.item, NOTES));
1587                 if(db_fget(e.item, URL))
1588                         fprintf(out, "URL:%s\r\n",
1589                                         db_fget(e.item, URL));
1590
1591                 fprintf(out, "END:VCARD\r\n\r\n");
1592
1593         }
1594
1595         return 0;
1596 }
1597
1598 /*
1599  * end of GnomeCard export filter
1600  */
1601
1602
1603 /*
1604  * mutt alias export filter
1605  */
1606
1607 static char *
1608 mutt_alias_genalias(int i)
1609 {
1610         char *tmp, *pos;
1611
1612         if(db_fget(i, NICK))
1613                 return xstrdup(db_fget(i, NICK));
1614
1615         tmp = xstrdup(db_name_get(i));
1616
1617         if( ( pos = strchr(tmp, ' ') ) )
1618                 *pos = 0;
1619
1620         strlower(tmp);
1621
1622         return tmp;
1623 }
1624
1625 static int
1626 mutt_alias_export(FILE *out, struct db_enumerator e)
1627 {
1628         char email[MAX_EMAIL_LEN];
1629         char *alias = NULL;
1630
1631         db_enumerate_items(e) {
1632                 alias = mutt_alias_genalias(e.item);
1633                 get_first_email(email, e.item);
1634                 fprintf(out, *email ? "alias %s %s <%s>\n": "alias %s %s%s\n",
1635                                 alias,
1636                                 db_name_get(e.item),
1637                                 email);
1638                 xfree(alias);
1639         }
1640
1641         return 0;
1642 }
1643
1644 /*
1645  * end of mutt alias export filter
1646  */
1647
1648
1649 /*
1650  * printable export filter
1651  */
1652
1653
1654 static void
1655 text_write_address_us(FILE *out, int i) {
1656         fprintf(out, "\n%s", db_fget(i, ADDRESS));
1657
1658         if(db_fget(i, ADDRESS2))
1659                 fprintf(out, "\n%s", db_fget(i, ADDRESS2));
1660
1661         if(db_fget(i, CITY))
1662                 fprintf(out, "\n%s", db_fget(i, CITY));
1663
1664         if(db_fget(i, STATE) || db_fget(i, ZIP)) {
1665                 fputc('\n', out);
1666
1667                 if(db_fget(i, STATE)) {
1668                         fprintf(out, "%s", db_fget(i, STATE));
1669                         if(db_fget(i, ZIP))
1670                                 fputc(' ', out);
1671                 }
1672
1673                 if(db_fget(i, ZIP))
1674                         fprintf(out, "%s", db_fget(i, ZIP));
1675         }
1676
1677         if(db_fget(i, COUNTRY))
1678                 fprintf(out, "\n%s", db_fget(i, COUNTRY));
1679 }
1680
1681
1682 static void
1683 text_write_address_uk(FILE *out, int i) {
1684         int j;
1685
1686         for(j = ADDRESS; j <= COUNTRY; j++)
1687                 if(db_fget(i, j))
1688                         fprintf(out, "\n%s", db_fget(i, j));
1689 }
1690
1691 static void
1692 text_write_address_eu(FILE *out, int i) {
1693         fprintf(out, "\n%s", db_fget(i, ADDRESS));
1694
1695         if(db_fget(i, ADDRESS2))
1696                 fprintf(out, "\n%s", db_fget(i, ADDRESS2));
1697
1698         if(db_fget(i, ZIP) || db_fget(i, CITY)) {
1699                 fputc('\n', out);
1700
1701                 if(db_fget(i, ZIP)) {
1702                         fprintf(out, "%s", db_fget(i, ZIP));
1703                         if(db_fget(i, CITY))
1704                                 fputc(' ', out);
1705                 }
1706
1707                 fprintf(out, "%s", safe_str(db_fget(i, CITY)));
1708         }
1709
1710         if(db_fget(i, STATE))
1711                 fprintf(out, "\n%s", db_fget(i, STATE));
1712
1713         if(db_fget(i, COUNTRY))
1714                 fprintf(out, "\n%s", db_fget(i, COUNTRY));
1715 }
1716
1717 static int
1718 text_export_database(FILE * out, struct db_enumerator e)
1719 {
1720         abook_list *emails, *em;
1721         int j;
1722         char *realname = get_real_name(), *str = NULL, *tmp;
1723         char *style = opt_get_str(STR_ADDRESS_STYLE);
1724
1725         fprintf(out,
1726                 "-----------------------------------------\n%s's address book\n"
1727                 "-----------------------------------------\n\n\n",
1728                 realname);
1729         free(realname);
1730
1731         db_enumerate_items(e) {
1732                 fprintf(out,
1733                         "-----------------------------------------\n\n");
1734                 fprintf(out, "%s", db_name_get(e.item));
1735                 if(db_fget(e.item, NICK) && *db_fget(e.item, NICK))
1736                         fprintf(out, "\n(%s)", db_fget(e.item, NICK));
1737                 fprintf(out, "\n");
1738
1739                 tmp = db_email_get(e.item);
1740                 if(*tmp) {
1741                         emails = csv_to_abook_list(tmp);
1742
1743                         fprintf(out, "\n");
1744                         for(em = emails; em; em = em->next)
1745                                 fprintf(out, "%s\n", em->data);
1746
1747                         abook_list_free(&emails);
1748                 }
1749                 free(tmp);
1750                 /* Print address */
1751                 if(db_fget(e.item, ADDRESS)) {
1752                         if(!safe_strcmp(style, "us"))   /* US like */
1753                                 text_write_address_us(out, e.item);
1754                         else if(!safe_strcmp(style, "uk"))      /* UK like */
1755                                 text_write_address_uk(out, e.item);
1756                         else    /* EU like */
1757                                 text_write_address_eu(out, e.item);
1758
1759                         fprintf(out, "\n");
1760                 }
1761
1762                 if((db_fget(e.item, PHONE)) ||
1763                         (db_fget(e.item, WORKPHONE)) ||
1764                         (db_fget(e.item, FAX)) ||
1765                         (db_fget(e.item, MOBILEPHONE))) {
1766                         fprintf(out, "\n");
1767                         for(j = PHONE; j <= MOBILEPHONE; j++)
1768                                 if(db_fget(e.item, j)) {
1769                                         get_field_info(field_id(j),
1770                                                         NULL, &str, NULL);
1771                                         fprintf(out, "%s: %s\n", str,
1772                                                 db_fget(e.item, j));
1773                                 }
1774                 }
1775
1776                 if(db_fget(e.item, URL))
1777                         fprintf(out, "\n%s\n", db_fget(e.item, URL));
1778                 if(db_fget(e.item, NOTES))
1779                         fprintf(out, "\n%s\n", db_fget(e.item, NOTES));
1780
1781                 fprintf(out, "\n");
1782         }
1783
1784         fprintf(out, "-----------------------------------------\n");
1785
1786         return 0;
1787 }
1788
1789 /*
1790  * end of printable export filter
1791  */
1792
1793 /*
1794  * elm alias export filter
1795  */
1796
1797 static int
1798 elm_alias_export(FILE *out, struct db_enumerator e)
1799 {
1800         char email[MAX_EMAIL_LEN];
1801         char *alias = NULL;
1802
1803         db_enumerate_items(e) {
1804                 alias = mutt_alias_genalias(e.item);
1805                 get_first_email(email, e.item);
1806                 fprintf(out, "%s = %s = %s\n",alias,db_name_get(e.item),email);
1807                 xfree(alias);
1808         }
1809
1810         return 0;
1811 }
1812
1813 /*
1814  * end of elm alias export filter
1815  */
1816
1817
1818 /*
1819  * Spruce export filter
1820  */
1821
1822 static int
1823 spruce_export_database (FILE *out, struct db_enumerator e)
1824 {
1825         char email[MAX_EMAIL_LEN];
1826
1827         fprintf(out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
1828
1829         db_enumerate_items(e) {
1830                 get_first_email(email, e.item);
1831                 if(strcmp(email, "")) {
1832                         fprintf(out, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
1833                                         e.item,
1834                                         db_name_get(e.item),
1835                                         email,
1836                                         safe_str(db_fget(e.item, NOTES))
1837                                         );
1838                 }
1839         }
1840
1841         fprintf (out, "# End of address book file.\n");
1842
1843         return 0;
1844 }
1845
1846 /*
1847  * end of Spruce export filter
1848  */
1849
1850 /*
1851  * wanderlust addressbook export filter
1852  */
1853
1854 static int
1855 wl_export_database(FILE *out, struct db_enumerator e)
1856 {
1857         char email[MAX_EMAIL_LEN];
1858
1859         fprintf(out, "# Wanderlust address book written by %s\n\n", PACKAGE);
1860         db_enumerate_items(e) {
1861                 get_first_email(email, e.item);
1862                 if(*email) {
1863                         fprintf(out,
1864                                 "%s\t\"%s\"\t\"%s\"\n",
1865                                 email,
1866                                 safe_str(db_fget(e.item, NICK)),
1867                                 safe_str(db_name_get(e.item))
1868                         );
1869                 }
1870         }
1871
1872         fprintf (out, "\n# End of address book file.\n");
1873
1874         return 0;
1875 }
1876
1877 /*
1878  * end of wanderlust addressbook export filter
1879  */
1880
1881 /*
1882  * BSD calendar export filter
1883  */
1884
1885 static int
1886 bsdcal_export_database(FILE *out, struct db_enumerator e)
1887 {
1888         db_enumerate_items(e) {
1889                 int year, month = 0, day = 0;
1890                 char *anniversary = db_fget(e.item, ANNIVERSARY);
1891
1892                 if(anniversary) {
1893                         parse_date_string(anniversary, &day, &month, &year);
1894
1895                         fprintf(out,
1896                                 _("%02d/%02d\tAnniversary of %s\n"),
1897                                 month,
1898                                 day,
1899                                 safe_str(db_name_get(e.item))
1900                         );
1901                 }
1902         }
1903
1904         return 0;
1905 }
1906
1907 /*
1908  * end of BSD calendar export filter
1909  */
1910