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