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