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