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