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