]> git.deb.at Git - pkg/abook.git/blob - filter.c
Imported Debian patch 0.5.5-1
[pkg/abook.git] / filter.c
1
2 /*
3  * $Id: filter.c,v 1.48.2.1 2005/10/26 19:45:23 jheinonen Exp $
4  *
5  * by JH <jheinonen@users.sourceforge.net>
6  *
7  * Copyright (C) Jaakko Heinonen
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <pwd.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17 #include "abook_curses.h"
18 #include "filter.h"
19 #include "abook.h"
20 #include "database.h"
21 #include "edit.h"
22 #include "gettext.h"
23 #include "list.h"
24 #include "misc.h"
25 #include "options.h"
26 #include "ui.h"
27 #include "xmalloc.h"
28 #include <assert.h>
29
30 extern 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);
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         int extra;
839
840         if(items < 1)
841                 return 2;
842
843         extra = (extra_column > 2 && extra_column < ITEM_FIELDS) ?
844                 extra_column : PHONE;
845
846         html_export_write_head(out, extra);
847
848         db_enumerate_items(e) {
849                 get_first_email(tmp, e.item);
850                 if (*tmp)
851                     fprintf(out, "<tr>\n<td><a href=\"mailto:%s\">%s</a>\n",
852                             tmp,
853                             database[e.item][NAME] );
854                 else
855                     fprintf(out, "<tr>\n<td>%s\n",
856                             database[e.item][NAME] );
857
858                 fprintf(out, "<td>%s\n<td>%s\n",
859                                 database[e.item][EMAIL],
860                                 safe_str(database[e.item][extra]) );
861                 fprintf(out, "</tr>\n\n");
862         }
863
864         html_export_write_tail(out);
865
866         return 0;
867 }
868
869
870 static void
871 html_export_write_head(FILE *out, int extra)
872 {
873         char *realname = get_real_name();
874
875         fprintf(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
876         fprintf(out, "<html>\n<head>\n <title>%s's addressbook</title>", realname );
877         fprintf(out, "\n</head>\n<body>\n");
878         fprintf(out, "\n<h2>%s's addressbook</h2>\n", realname );
879         fprintf(out, "<br><br>\n\n");
880
881         fprintf(out, "<table border=\"1\" align=\"center\">\n");
882         fprintf(out, "\n<tr><th>Name<th>E-mail address(es)<th>%s</tr>\n\n",
883                         abook_fields[extra].name);
884
885         free(realname);
886 }
887
888 static void
889 html_export_write_tail(FILE *out)
890 {
891         fprintf(out, "\n</table>\n");
892         fprintf(out, "\n</body>\n</html>\n");
893 }
894
895 /*
896  * end of html export filter
897  */
898
899
900 /*
901  * pine addressbook import filter
902  */
903
904 #define PINE_BUF_SIZE 2048
905
906 static void
907 pine_fixbuf(char *buf)
908 {
909         int i,j;
910
911         for(i=0,j=0; j < (int)strlen(buf); i++, j++)
912                 buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
913 }
914
915 static void
916 pine_convert_emails(char *s)
917 {
918         int i;
919         char *tmp;
920
921         if(s == NULL || *s != '(')
922                 return;
923
924         for(i=0; s[i]; i++ )
925                 s[i] = s[i+1];
926
927         if( ( tmp = strchr(s,')')) )
928                 *tmp=0;
929
930         for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
931                 if(i > MAX_EMAILS - 1) {
932                         *tmp = 0;
933                         break;
934                 }
935
936 }
937
938 static void
939 pine_parse_buf(char *buf)
940 {
941         list_item item;
942         char *start = buf;
943         char *end;
944         char tmp[PINE_BUF_SIZE];
945         int i, len, last;
946         int pine_conv_table[]= {NICK, NAME, EMAIL, -1, NOTES};
947
948         memset(&item, 0, sizeof(item));
949
950         for(i=0, last=0; !last ; i++) {
951                 if( !(end = strchr(start, '\t')) )
952                         last=1;
953
954                 len = last ? strlen(start) : (int) (end-start);
955                 len = min(len, PINE_BUF_SIZE - 1);
956
957                 if(i < (int)(sizeof(pine_conv_table) / sizeof(*pine_conv_table))
958                                 && pine_conv_table[i] >= 0) {
959                         strncpy(tmp, start, len);
960                         tmp[len] = 0;
961                         if(*tmp)
962                                 item[pine_conv_table[i]] = xstrdup(tmp);
963                 }
964                 start = end + 1;
965         }
966
967         pine_convert_emails(item[EMAIL]);
968         add_item2database(item);
969 }
970
971
972 #define LINESIZE        1024
973
974 static int
975 pine_parse_file(FILE *in)
976 {
977         char line[LINESIZE];
978         char *buf = NULL;
979         char *ptr;
980         int i;
981
982         fgets(line, LINESIZE, in);
983
984         while(!feof(in)) {
985                 for(i = 2;;i++) {
986                         buf = xrealloc(buf, i*LINESIZE);
987                         if(i == 2)
988                                 strcpy(buf, line);
989                         fgets(line, LINESIZE, in);
990                         ptr=(char *)&line;
991                         if(*ptr != ' ' || feof(in))
992                                 break;
993                         else
994                                 while(*ptr == ' ')
995                                         ptr++;
996
997                         strcat(buf, ptr);
998                 }
999                 if(*buf == '#') {
1000                         xfree(buf);
1001                         continue;
1002                 }
1003                 pine_fixbuf(buf);
1004
1005                 pine_parse_buf(buf);
1006
1007                 xfree(buf);
1008         }
1009
1010         return 0;
1011 }
1012
1013 /*
1014  * end of pine addressbook import filter
1015  */
1016
1017
1018 /*
1019  * pine addressbook export filter
1020  *
1021  *  filter doesn't wrap the lines as it should but Pine seems to handle
1022  *  created files without problems - JH
1023  */
1024
1025 static int
1026 pine_export_database(FILE *out, struct db_enumerator e)
1027 {
1028         db_enumerate_items(e) {
1029                 fprintf(out, have_multiple_emails(e.item) ?
1030                                 "%s\t%s\t(%s)\t\t%s\n" : "%s\t%s\t%s\t\t%s\n",
1031                                 safe_str(database[e.item][NICK]),
1032                                 safe_str(database[e.item][NAME]),
1033                                 safe_str(database[e.item][EMAIL]),
1034                                 safe_str(database[e.item][NOTES])
1035                                 );
1036         }
1037
1038         return 0;
1039 }
1040
1041 /*
1042  * end of pine addressbook export filter
1043  */
1044
1045
1046 /*
1047  * csv import filter
1048  */
1049
1050 /* FIXME
1051  * these files should be parsed according to a certain
1052  * lay out, or the default if layout is not given, at
1053  * the moment only default is done...
1054  */
1055
1056 #define CSV_COMMENT_CHAR        '#'
1057 #define CSV_DUPLICATE_SEPARATOR " "
1058 #define CSV_TABLE_SIZE(t)       (sizeof (t) / sizeof *(t))
1059
1060 static int csv_conv_table[] = {
1061         NAME,
1062         EMAIL,
1063         PHONE,
1064         NOTES,
1065         NICK
1066 };
1067
1068 static int allcsv_conv_table[] = {
1069         NAME,
1070         EMAIL,
1071         ADDRESS,
1072         ADDRESS2,
1073         CITY,
1074         STATE,
1075         ZIP,
1076         COUNTRY,
1077         PHONE,
1078         WORKPHONE,
1079         FAX,
1080         MOBILEPHONE,
1081         NICK,
1082         URL,
1083         NOTES,
1084         CUSTOM1,
1085         CUSTOM2,
1086         CUSTOM3,
1087         CUSTOM4,
1088         CUSTOM5,
1089 };
1090
1091 static int palmcsv_conv_table[] = {
1092         NAME,           /* Last name */
1093         NAME,           /* First name */
1094         NOTES,          /* Title */
1095         NICK,           /* Company */
1096         WORKPHONE,
1097         PHONE,
1098         FAX,
1099         MOBILEPHONE,
1100         EMAIL,
1101         ADDRESS,
1102         CITY,
1103         STATE,
1104         ZIP,
1105         COUNTRY,
1106         CUSTOM1,
1107         CUSTOM2,
1108         CUSTOM3,
1109         CUSTOM4,
1110         CUSTOM5,
1111 };
1112
1113 static void
1114 csv_convert_emails(char *s)
1115 {
1116         int i;
1117         char *tmp;
1118
1119         if(s == NULL)
1120                 return;
1121
1122         for(i = 1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1)
1123                 if(i > MAX_EMAILS - 1) {
1124                         *tmp = 0;
1125                         break;
1126                 }
1127
1128 }
1129
1130 static char *
1131 csv_remove_quotes(char *s)
1132 {
1133         char *copy, *trimmed;
1134         int len;
1135
1136         copy = trimmed = xstrdup(s);
1137         strtrim(trimmed);
1138
1139         len = strlen(trimmed);
1140         if(trimmed[len - 1] == '\"' && *trimmed == '\"') {
1141                 if(len < 3) {
1142                         xfree(copy);
1143                         return NULL;
1144                 }
1145                 trimmed[len - 1] = 0;
1146                 trimmed++;
1147                 trimmed = xstrdup(trimmed);
1148                 free(copy);
1149                 return trimmed;
1150         }
1151
1152         xfree(copy);
1153         return xstrdup(s);
1154 }
1155
1156 static int
1157 csv_field_to_item(int *table_base, size_t table_size, int field)
1158 {
1159         if(field < table_size)
1160                 return table_base[field];
1161
1162         return -1;
1163 }
1164
1165 static void
1166 csv_store_item(list_item item, int i, char *s)
1167 {
1168         char *newstr = NULL;
1169
1170         if(!s || !*s)
1171                 return;
1172
1173         if( !(newstr = csv_remove_quotes(s)) )
1174                 return;
1175
1176         if(i >= 0) {
1177                 if (item[i] != NULL) {
1178                         char *oldstr = item[i];
1179
1180                         item[i] = strconcat(newstr, CSV_DUPLICATE_SEPARATOR,
1181                                 oldstr, NULL);
1182                         xfree(newstr);
1183                         xfree(oldstr);
1184                 } else {
1185                         item[i] = newstr;
1186                 }
1187         } else {
1188                 xfree(newstr);
1189         }
1190 }
1191
1192 static int
1193 csv_is_valid_quote_end(char *p)
1194 {
1195         if(*p != '\"')
1196                 return FALSE;
1197
1198         for(p++; *p; p++) {
1199                 if(*p == ',')
1200                         return TRUE;
1201                 else if(!ISSPACE(*p))
1202                         return FALSE;
1203         }
1204
1205         return TRUE;
1206 }
1207
1208 static int
1209 csv_is_valid_quote_start(char *p)
1210 {
1211         for(; *p; p++) {
1212                 if(*p == '\"')
1213                         return TRUE;
1214                 else if(!ISSPACE(*p))
1215                         return FALSE;
1216         }
1217
1218         return FALSE;
1219 }
1220
1221 static void
1222 csv_parse_line(char *line, int *table_base, size_t table_size)
1223 {
1224         char *p, *start;
1225         int field;
1226         bool in_quote = FALSE;
1227         list_item item;
1228
1229         memset(item, 0, sizeof(item));
1230
1231         for(p = start = line, field = 0; *p; p++) {
1232                 if(in_quote) {
1233                         if(csv_is_valid_quote_end(p))
1234                                 in_quote = FALSE;
1235                 } else {
1236                         if ( (((p - start) / sizeof (char)) < 2 ) &&
1237                                 csv_is_valid_quote_start(p) )
1238                                 in_quote = TRUE;
1239                 }
1240
1241                 if(*p == ',' && !in_quote) {
1242                         *p = 0;
1243                         csv_field_to_item(table_base, table_size, field);
1244                         csv_store_item(item,
1245                                 csv_field_to_item(table_base,
1246                                                         table_size, field),
1247                                 start);
1248                         field++;
1249                         start = p + 1;
1250                 }
1251         }
1252         /*
1253          * store last field
1254          */
1255         csv_store_item(item, csv_field_to_item(table_base, table_size, field),
1256                 start);
1257
1258         csv_convert_emails(item[EMAIL]);
1259         add_item2database(item);
1260 }
1261
1262 static int
1263 csv_parse_file_common(FILE *in, int *conv_table, size_t table_size)
1264 {
1265         char *line = NULL;
1266
1267         while(!feof(in)) {
1268                 line = getaline(in);
1269
1270                 if(line && *line && *line != CSV_COMMENT_CHAR)
1271                         csv_parse_line(line, conv_table, table_size);
1272
1273                 xfree(line);
1274         }
1275
1276         return 0;
1277 }
1278
1279 static int
1280 csv_parse_file(FILE *in)
1281 {
1282         return csv_parse_file_common(in, csv_conv_table,
1283                 CSV_TABLE_SIZE(csv_conv_table));
1284 }
1285
1286 static int
1287 allcsv_parse_file(FILE *in)
1288 {
1289         return csv_parse_file_common(in, allcsv_conv_table,
1290                 CSV_TABLE_SIZE(allcsv_conv_table));
1291 }
1292
1293 static int
1294 palmcsv_parse_file(FILE *in)
1295 {
1296         return csv_parse_file_common(in, palmcsv_conv_table,
1297                 CSV_TABLE_SIZE(palmcsv_conv_table));
1298 }
1299
1300 /*
1301  * end of csv import filter
1302  */
1303
1304 /*
1305  * csv addressbook export filters
1306  */
1307
1308 #define CSV_LAST                (-1)
1309 #define CSV_UNDEFINED           (-2)
1310 #define CSV_SPECIAL(X)          (-3 - (X))
1311 #define CSV_IS_SPECIAL(X)       ((X) <= -3)
1312
1313 static int
1314 csv_export_common(FILE *out, struct db_enumerator e,
1315                 int fields[], void (*special_func)(FILE *, int, int))
1316 {
1317         int i;
1318
1319         db_enumerate_items(e) {
1320                 for(i = 0; fields[i] != CSV_LAST; i++) {
1321                         if(fields[i] == CSV_UNDEFINED)
1322                                 fprintf(out, "\"\"");
1323                         else if(CSV_IS_SPECIAL(fields[i])) {
1324                                 if(special_func)
1325                                         (*special_func)(out, e.item, fields[i]);
1326                         } else
1327                                 /*fprintf(out,(
1328                         strchr(safe_str(database[e.item][fields[i]]), ',') ||
1329                         strchr(safe_str(database[e.item][fields[i]]), '\"')) ?
1330                                 "\"%s\"" : "%s",
1331                                 safe_str(database[e.item][fields[i]])
1332                                 );*/
1333                                 fprintf(out, "\"%s\"",
1334                                         safe_str(database[e.item][fields[i]]));
1335
1336                         if(fields[i + 1] != CSV_LAST)
1337                                 fputc(',', out);
1338                 }
1339                 fputc('\n', out);
1340         }
1341
1342         return 0;
1343 }
1344
1345 static int
1346 csv_export_database(FILE *out, struct db_enumerator e)
1347 {
1348         int csv_export_fields[] = {
1349                 NAME,
1350                 EMAIL,
1351                 PHONE,
1352                 NOTES,
1353                 NICK,
1354                 CSV_LAST
1355         };
1356
1357         csv_export_common(out, e, csv_export_fields, NULL);
1358
1359         return 0;
1360 }
1361
1362 static int
1363 allcsv_export_database(FILE *out, struct db_enumerator e)
1364 {
1365         /*
1366          * TODO: Should get these atomatically from abook_fileds
1367          *  - JH
1368          */
1369         int allcsv_export_fields[] = {
1370                 NAME,
1371                 EMAIL,
1372                 ADDRESS,
1373                 ADDRESS2,
1374                 CITY,
1375                 STATE,
1376                 ZIP,
1377                 COUNTRY,
1378                 PHONE,
1379                 WORKPHONE,
1380                 FAX,
1381                 MOBILEPHONE,
1382                 NICK,
1383                 URL,
1384                 NOTES,
1385                 CUSTOM1,
1386                 CUSTOM2,
1387                 CUSTOM3,
1388                 CUSTOM4,
1389                 CUSTOM5,
1390                 CSV_LAST
1391         };
1392
1393         fprintf(out, "#");
1394         fprintf(out, "\"NAME\",");
1395         fprintf(out, "\"EMAIL\",");
1396         fprintf(out, "\"ADDRESS\",");
1397         fprintf(out, "\"ADDRESS2\",");
1398         fprintf(out, "\"CITY\",");
1399         fprintf(out, "\"STATE\",");
1400         fprintf(out, "\"ZIP\",");
1401         fprintf(out, "\"COUNTRY\",");
1402         fprintf(out, "\"PHONE\",");
1403         fprintf(out, "\"WORKPHONE\",");
1404         fprintf(out, "\"FAX\",");
1405         fprintf(out, "\"MOBILEPHONE\",");
1406         fprintf(out, "\"NICK\",");
1407         fprintf(out, "\"URL\",");
1408         fprintf(out, "\"NOTES\",");
1409         fprintf(out, "\"CUSTOM1\",");
1410         fprintf(out, "\"CUSTOM2\",");
1411         fprintf(out, "\"CUSTOM3\",");
1412         fprintf(out, "\"CUSTOM4\",");
1413         fprintf(out, "\"CUSTOM5\"\n");
1414
1415         csv_export_common(out, e, allcsv_export_fields, NULL);
1416
1417         return 0;
1418 }
1419
1420 /*
1421  * palm csv
1422  */
1423
1424 #define PALM_CSV_NAME   CSV_SPECIAL(0)
1425 #define PALM_CSV_END    CSV_SPECIAL(1)
1426 #define PALM_CSV_CAT    CSV_SPECIAL(2)
1427
1428 static void
1429 palm_split_and_write_name(FILE *out, char *name)
1430 {
1431         char *p;
1432
1433         assert(name);
1434
1435         if ( (p = strchr(name, ' ')) ) {
1436                 /*
1437                  * last name first
1438                  */
1439                 fprintf(out, "\"%s\",\"" , p + 1);
1440                 fwrite((void *)name, p - name, sizeof(char), out);
1441                 fputc('\"', out);
1442         } else {
1443                 fprintf(out, "\"%s\"", safe_str(name));
1444         }
1445 }
1446
1447 static void
1448 palm_csv_handle_specials(FILE *out, int item, int field)
1449 {
1450         switch(field) {
1451                 case PALM_CSV_NAME:
1452                         palm_split_and_write_name(out, database[item][NAME]);
1453                         break;
1454                 case PALM_CSV_CAT:
1455                         fprintf(out, "\"abook\"");
1456                         break;
1457                 case PALM_CSV_END:
1458                         fprintf(out, "\"0\"");
1459                         break;
1460                 default:
1461                         assert(0);
1462         }
1463 }
1464
1465 static int
1466 palm_export_database(FILE *out, struct db_enumerator e)
1467 {
1468         int palm_export_fields[] = {
1469                 PALM_CSV_NAME,          /* LASTNAME, FIRSTNAME  */
1470                 CSV_UNDEFINED,          /* TITLE                */
1471                 CSV_UNDEFINED,          /* COMPANY              */
1472                 WORKPHONE,              /* WORK PHONE           */
1473                 PHONE,                  /* HOME PHONE           */
1474                 FAX,                    /* FAX                  */
1475                 MOBILEPHONE,            /* OTHER                */
1476                 EMAIL,                  /* EMAIL                */
1477                 ADDRESS,                /* ADDRESS              */
1478                 CITY,                   /* CITY                 */
1479                 STATE,                  /* STATE                */
1480                 ZIP,                    /* ZIP                  */
1481                 COUNTRY,                /* COUNTRY              */
1482                 NICK,                   /* DEFINED 1            */
1483                 URL,                    /* DEFINED 2            */
1484                 CSV_UNDEFINED,          /* DEFINED 3            */
1485                 CSV_UNDEFINED,          /* DEFINED 4            */
1486                 NOTES,                  /* NOTE                 */
1487                 PALM_CSV_END,           /* "0"                  */
1488                 PALM_CSV_CAT,           /* CATEGORY             */
1489                 CSV_LAST
1490         };
1491
1492         csv_export_common(out, e, palm_export_fields, palm_csv_handle_specials);
1493
1494         return 0;
1495 }
1496
1497 /*
1498  * end of csv export filters
1499  */
1500
1501 /*
1502  * GnomeCard (VCard) addressbook export filter
1503  */
1504
1505 static int
1506 gcrd_export_database(FILE *out, struct db_enumerator e)
1507 {
1508         char emails[MAX_EMAILS][MAX_EMAIL_LEN];
1509         int j;
1510         char *name;
1511
1512         db_enumerate_items(e) {
1513                 fprintf(out, "BEGIN:VCARD\nFN:%s\n",
1514                                 safe_str(database[e.item][NAME]));
1515
1516                 name = get_surname(database[e.item][NAME]);
1517                 for( j = strlen(database[e.item][NAME]) - 1; j >= 0; j-- ) {
1518                         if(database[e.item][NAME][j] == ' ')
1519                                 break;
1520                 }
1521                 fprintf(out, "N:%s;%.*s\n",
1522                         safe_str(name),
1523                         j,
1524                         safe_str(database[e.item][NAME])
1525                         );
1526
1527                 free(name);
1528
1529                 if ( database[e.item][ADDRESS] )
1530                         fprintf(out, "ADR:;;%s;%s;%s;%s;%s;%s\n",
1531                                 safe_str(database[e.item][ADDRESS]),
1532                                 safe_str(database[e.item][ADDRESS2]),
1533                                 safe_str(database[e.item][CITY]),
1534                                 safe_str(database[e.item][STATE]),
1535                                 safe_str(database[e.item][ZIP]),
1536                                 safe_str(database[e.item][COUNTRY])
1537                                 );
1538
1539                 if (database[e.item][PHONE])
1540                         fprintf(out, "TEL;HOME:%s\n", database[e.item][PHONE]);
1541                 if (database[e.item][WORKPHONE])
1542                         fprintf(out, "TEL;WORK:%s\n", database[e.item][WORKPHONE]);
1543                 if (database[e.item][FAX])
1544                         fprintf(out, "TEL;FAX:%s\n", database[e.item][FAX]);
1545                 if (database[e.item][MOBILEPHONE])
1546                         fprintf(out, "TEL;CELL:%s\n", database[e.item][MOBILEPHONE]);
1547
1548                 if ( database[e.item][EMAIL] ) {
1549                         split_emailstr(e.item, emails);
1550                         for(j=0; j < MAX_EMAILS ; j++) {
1551                                 if ( *emails[j] )
1552                                         fprintf(out, "EMAIL;INTERNET:%s\n",
1553                                                 emails[j]);
1554                         }
1555                 }
1556
1557                 if ( database[e.item][NOTES] )
1558                         fprintf(out, "NOTE:%s\n", database[e.item][NOTES]);
1559                 if (database[e.item][URL])
1560                         fprintf(out, "URL:%s\n",  database[e.item][URL]);
1561
1562                 fprintf(out, "END:VCARD\n\n");
1563
1564         }
1565
1566         return 0;
1567 }
1568
1569 /*
1570  * end of GnomeCard export filter
1571  */
1572
1573
1574 /*
1575  * mutt alias export filter
1576  */
1577
1578 static char *
1579 mutt_alias_genalias(int i)
1580 {
1581         char *tmp, *pos;
1582
1583         if(database[i][NICK])
1584                 return xstrdup(database[i][NICK]);
1585
1586         tmp = xstrdup(database[i][NAME]);
1587
1588         if( ( pos = strchr(tmp, ' ') ) )
1589                 *pos = 0;
1590
1591         strlower(tmp);
1592
1593         return tmp;
1594 }
1595
1596 static int
1597 mutt_alias_export(FILE *out, struct db_enumerator e)
1598 {
1599         char email[MAX_EMAIL_LEN];
1600         char *alias = NULL;
1601
1602         db_enumerate_items(e) {
1603                 alias = mutt_alias_genalias(e.item);
1604
1605                 get_first_email(email, e.item);
1606                 fprintf(out, *email ? "alias %s %s <%s>\n": "alias %s %s%s\n",
1607                                 alias,
1608                                 database[e.item][NAME],
1609                                 email);
1610                 xfree(alias);
1611         }
1612
1613         return 0;
1614 }
1615
1616 /*
1617  * end of mutt alias export filter
1618  */
1619
1620
1621 /*
1622  * printable export filter
1623  */
1624
1625
1626 static void
1627 text_write_address_us(FILE *out, int i) {
1628         fprintf(out, "\n%s", database[i][ADDRESS]);
1629
1630         if (database[i][ADDRESS2])
1631                 fprintf(out, "\n%s", database[i][ADDRESS2]);
1632
1633         if (database[i][CITY])
1634                 fprintf(out, "\n%s", database[i][CITY]);
1635
1636         if (database[i][STATE] || database[i][ZIP]) {
1637                 fputc('\n', out);
1638
1639                 if(database[i][STATE]) {
1640                         fprintf(out, "%s", database[i][STATE]);
1641                         if(database[i][ZIP])
1642                                 fputc(' ', out);
1643                 }
1644
1645                 if(database[i][ZIP])
1646                         fprintf(out, "%s", database[i][ZIP]);
1647         }
1648
1649         if (database[i][COUNTRY])
1650                 fprintf(out, "\n%s", database[i][COUNTRY]);
1651 }
1652
1653
1654 static void
1655 text_write_address_uk(FILE *out, int i) {
1656         int j;
1657
1658         for (j = ADDRESS; j <= COUNTRY; j++)
1659                 if (database[i][j])
1660                         fprintf(out, "\n%s", database[i][j]);
1661 }
1662
1663 static void
1664 text_write_address_eu(FILE *out, int i) {
1665         fprintf(out, "\n%s", database[i][ADDRESS]);
1666
1667         if (database[i][ADDRESS2])
1668                 fprintf(out, "\n%s", database[i][ADDRESS2]);
1669
1670         if (database[i][ZIP] || database[i][CITY]) {
1671                 fputc('\n', out);
1672
1673                 if(database[i][ZIP]) {
1674                         fprintf(out, "%s", database[i][ZIP]);
1675                         if(database[i][CITY])
1676                                 fputc(' ', out);
1677                 }
1678
1679                 if(database[i][CITY])
1680                         fprintf(out, "%s", database[i][CITY]);
1681         }
1682
1683         if (database[i][STATE])
1684                 fprintf(out, "\n%s", database[i][STATE]);
1685
1686         if (database[i][COUNTRY])
1687                 fprintf(out, "\n%s", database[i][COUNTRY]);
1688 }
1689
1690 static int
1691 text_export_database(FILE * out, struct db_enumerator e)
1692 {
1693         char emails[MAX_EMAILS][MAX_EMAIL_LEN];
1694         int j;
1695         char *realname = get_real_name();
1696         char *style = opt_get_str(STR_ADDRESS_STYLE);
1697
1698         fprintf(out,
1699                 "-----------------------------------------\n%s's address book\n"
1700                 "-----------------------------------------\n\n\n",
1701                 realname);
1702         free(realname);
1703
1704         db_enumerate_items(e) {
1705                 fprintf(out,
1706                         "-----------------------------------------\n\n");
1707                 fprintf(out, "%s", database[e.item][NAME]);
1708                 if (database[e.item][NICK] && *database[e.item][NICK])
1709                         fprintf(out, "\n(%s)", database[e.item][NICK]);
1710                 fprintf(out, "\n");
1711
1712                 if (*database[e.item][EMAIL]) {
1713                         fprintf(out, "\n");
1714                         split_emailstr(e.item, emails);
1715                         for (j = 0; j < MAX_EMAILS; j++)
1716                                 if (*emails[j])
1717                                         fprintf(out, "%s\n", emails[j]);
1718                 }
1719                 /* Print address */
1720                 if (database[e.item][ADDRESS]) {
1721                         if (!safe_strcmp(style, "us"))  /* US like */
1722                                 text_write_address_us(out, e.item);
1723                         else if (!safe_strcmp(style, "uk"))     /* UK like */
1724                                 text_write_address_uk(out, e.item);
1725                         else    /* EU like */
1726                                 text_write_address_eu(out, e.item);
1727
1728                         fprintf(out, "\n");
1729                 }
1730
1731                 if ((database[e.item][PHONE]) ||
1732                         (database[e.item][WORKPHONE]) ||
1733                         (database[e.item][FAX]) ||
1734                         (database[e.item][MOBILEPHONE])) {
1735                         fprintf(out, "\n");
1736                         for (j = PHONE; j <= MOBILEPHONE; j++)
1737                                 if (database[e.item][j])
1738                                         fprintf(out, "%s: %s\n",
1739                                                 abook_fields[j].name,
1740                                                 database[e.item][j]);
1741                 }
1742
1743                 if (database[e.item][URL])
1744                         fprintf(out, "\n%s\n", database[e.item][URL]);
1745                 if (database[e.item][NOTES])
1746                         fprintf(out, "\n%s\n", database[e.item][NOTES]);
1747
1748                 fprintf(out, "\n");
1749         }
1750
1751         fprintf(out, "-----------------------------------------\n");
1752
1753         return 0;
1754 }
1755
1756 /*
1757  * end of printable export filter
1758  */
1759
1760 /*
1761  * elm alias export filter
1762  */
1763
1764 static int
1765 elm_alias_export(FILE *out, struct db_enumerator e)
1766 {
1767         char email[MAX_EMAIL_LEN];
1768         char *alias = NULL;
1769
1770         db_enumerate_items(e) {
1771                 alias = mutt_alias_genalias(e.item);
1772                 get_first_email(email, e.item);
1773                 fprintf(out, "%s = %s = %s\n",
1774                                 alias,
1775                                 database[e.item][NAME],
1776                                 email);
1777                 xfree(alias);
1778         }
1779
1780         return 0;
1781 }
1782
1783 /*
1784  * end of elm alias export filter
1785  */
1786
1787
1788 /*
1789  * Spruce export filter
1790  */
1791
1792 static int
1793 spruce_export_database (FILE *out, struct db_enumerator e)
1794 {
1795         char email[MAX_EMAIL_LEN];
1796
1797         fprintf (out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
1798
1799         db_enumerate_items(e) {
1800                 if(strcmp (safe_str(database[e.item][EMAIL]), "")) {
1801                         get_first_email(email, e.item);
1802                         fprintf(out, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
1803                                         e.item,
1804                                         database[e.item][NAME],
1805                                         email,
1806                                         safe_str(database[e.item][NOTES])
1807                                         );
1808                 }
1809         }
1810
1811         fprintf (out, "# End of address book file.\n");
1812
1813         return 0;
1814 }
1815
1816 /*
1817  * end of Spruce export filter
1818  */
1819
1820 /*
1821  * wanderlust addressbook export filter
1822  */
1823
1824 static int
1825 wl_export_database(FILE *out, struct db_enumerator e)
1826 {
1827         char emails[MAX_EMAILS][MAX_EMAIL_LEN];
1828
1829         fprintf (out, "# Wanderlust address book written by %s\n\n", PACKAGE);
1830         db_enumerate_items(e) {
1831                 split_emailstr(e.item, emails);
1832                 if (**emails) {
1833                         fprintf(out,
1834                                 "%s\t\"%s\"\t\"%s\"\n",
1835                                 *emails,
1836                                 safe_str(database[e.item][NICK]),
1837                                 safe_str(database[e.item][NAME])
1838                         );
1839                 }
1840         }
1841
1842         fprintf (out, "\n# End of address book file.\n");
1843
1844         return 0;
1845 }
1846
1847 /*
1848  * end of wanderlust addressbook export filter
1849  */
1850