]> git.deb.at Git - pkg/abook.git/blob - filter.c
Ids added
[pkg/abook.git] / filter.c
1
2 /*
3  * $Id$
4  *
5  * by JH <jheinonen@bigfoot.com>
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/types.h>
16 #include "abook_curses.h"
17 #include "filter.h"
18 #include "abook.h"
19 #include "database.h"
20 #include "edit.h"
21 #include "list.h"
22 #include "misc.h"
23 #include "options.h"
24
25 extern int items;
26 extern list_item *database;
27 extern struct abook_field abook_fields[];
28
29 /*
30  * function declarations
31  */
32
33 static int      ldif_parse_file(FILE *handle);
34 static int      mutt_parse_file(FILE *in);
35 static int      pine_parse_file(FILE *in);
36
37 static int      ldif_export_database(FILE *out);
38 static int      html_export_database(FILE *out);
39 static int      pine_export_database(FILE *out);
40 static int      csv_export_database(FILE *out);
41 static int      gcrd_export_database(FILE *out);
42 static int      mutt_alias_export(FILE *out);
43 static int      elm_alias_export(FILE *out);
44 static int      text_export_database(FILE *out);
45 static int      spruce_export_database(FILE *out);
46
47
48 struct abook_filter i_filters[] = {
49         { "abook", "abook native format", parse_database },
50         { "ldif", "ldif / Netscape addressbook", ldif_parse_file },
51         { "mutt", "mutt alias (beta)", mutt_parse_file },
52         { "pine", "pine addressbook", pine_parse_file },
53         { "\0", NULL, NULL }
54 };
55
56 struct abook_filter e_filters[] = {
57         { "abook", "abook native format", write_database },
58         { "ldif", "ldif / Netscape addressbook (.4ld)", ldif_export_database },
59         { "mutt", "mutt alias", mutt_alias_export },
60         { "html", "html document", html_export_database },
61         { "pine", "pine addressbook", pine_export_database },
62         { "gcrd", "GnomeCard (VCard) addressbook", gcrd_export_database },
63         { "csv", "comma separated values", csv_export_database },
64         { "elm", "elm alias", elm_alias_export },
65         { "text", "plain text", text_export_database },
66         { "spruce", "Spruce address book", spruce_export_database },
67         { "\0", NULL, NULL }
68 };
69
70 /*
71  * common functions
72  */
73
74 void
75 print_filters()
76 {
77         int i;
78         
79         puts("input:");
80         for(i=0; *i_filters[i].filtname ; i++)
81                 printf("\t%s\t%s\n", i_filters[i].filtname,
82                         i_filters[i].desc);
83
84         putchar('\n');
85         
86         puts("output:");
87         for(i=0; *e_filters[i].filtname ; i++)
88                 printf("\t%s\t%s\n", e_filters[i].filtname,
89                         e_filters[i].desc);
90
91         putchar('\n');
92 }
93
94 static int
95 number_of_filters(struct abook_filter * filters)
96 {
97         int i;
98
99         for(i=0; *filters[i].filtname ; i++)
100                 ;
101
102         return i;
103 }
104
105 static char *
106 get_real_name()
107 {
108         char *username = getenv("USER");
109         struct passwd *pwent;
110         int rtn;
111         char *tmp;
112
113         pwent = getpwnam(username);
114
115         if( (tmp = malloc(strlen(pwent->pw_gecos) +1)) == NULL)
116                 return strdup(username);
117
118         rtn = sscanf(pwent->pw_gecos, "%[^,]", tmp);
119         if (rtn == EOF || rtn == 0) {
120                 free(tmp);
121                 return strdup(username);
122         } else
123                 return tmp;
124 }
125
126 /*
127  * import
128  */
129         
130 static int              i_read_file(char *filename, int (*func) (FILE *in));
131
132 static void
133 import_screen()
134 {
135         int i;
136         
137         clear();
138
139         refresh_statusline();
140         headerline("import database");
141
142         mvaddstr(3, 1, "please select a filter");
143         
144
145         for(i=0; *i_filters[i].filtname ; i++)
146                 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
147                         i_filters[i].filtname,
148                         i_filters[i].desc);
149
150         mvprintw(6 + i, 6, "x -\tcancel");
151 }
152
153 int
154 import_database()
155 {
156         int filter;
157         char *filename;
158         int tmp = items;
159
160         import_screen();
161         
162         filter = getch() - 'a';
163         if(filter == 'x' - 'a' || filter >= number_of_filters(e_filters) ||
164                         filter < 0) {
165                 refresh_screen();
166                 return 1;
167         }
168         
169         mvaddstr(5+filter, 2, "->");
170         
171         filename = ask_filename("Filename: ", 1);
172         if( !filename ) {
173                 refresh_screen();
174                 return 2;
175         }
176                 
177         if(  i_read_file(filename, i_filters[filter].func ) )
178                 statusline_msg("Error occured while opening the file");
179         else
180         if( tmp == items )
181                 statusline_msg("Hmm.., file seems not to be a valid file");
182         
183         refresh_screen();
184         free(filename);
185
186         return 0;
187 }
188
189
190
191 static int
192 i_read_file(char *filename, int (*func) (FILE *in))
193 {
194         FILE *in;
195         int ret = 0;
196
197         if( ( in = fopen( filename, "r" ) ) == NULL )
198                 return 1;
199
200         ret = (*func) (in);
201
202         fclose(in);
203
204         return ret;     
205 }
206
207 int
208 import(char filtname[FILTNAME_LEN], char *filename)
209 {
210         int i;
211         int tmp = items;
212         int ret = 0;
213
214         for(i=0;; i++) {
215                 if( ! strncmp(i_filters[i].filtname, filtname, FILTNAME_LEN) )
216                         break;
217                 if( ! *i_filters[i].filtname ) {
218                         i = -1;
219                         break;
220                 }
221         }
222
223         if( i<0 )
224                 return -1;
225
226         if( !strcmp(filename, "-") )
227                 ret = (*i_filters[i].func) (stdin);
228         else
229                 ret =  i_read_file(filename, i_filters[i].func);
230         
231         if( tmp == items )
232                 ret = 1;
233         
234         return ret;
235 }
236
237 /*
238  * export
239  */
240
241 static int              e_write_file(char *filename, int (*func) (FILE *in));
242
243 static void
244 export_screen()
245 {
246         int i;
247         
248         clear();
249
250
251         refresh_statusline();
252         headerline("export database");
253
254         mvaddstr(3, 1, "please select a filter");
255         
256
257         for(i=0; *e_filters[i].filtname ; i++)
258                 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
259                         e_filters[i].filtname,
260                         e_filters[i].desc);
261
262         mvprintw(6 + i, 6, "x -\tcancel");
263 }
264
265 int
266 export_database()
267 {
268         int filter;
269         char *filename;
270
271         export_screen();
272         
273         filter = getch() - 'a';
274         if(filter == 'x' - 'a' || filter >= number_of_filters(e_filters) ||
275                         filter < 0) {
276                 refresh_screen();
277                 return 1;
278         }
279         
280         mvaddstr(5+filter, 2, "->");
281         
282         filename = ask_filename("Filename: ", 0);
283         if( !filename ) {
284                 refresh_screen();
285                 return 2;
286         }
287         
288         if(  e_write_file(filename, e_filters[filter].func ) )
289                 statusline_msg("Error occured while exporting");
290         
291         refresh_screen();
292         free(filename);
293
294         return 0;
295 }
296
297 static int
298 e_write_file(char *filename, int (*func) (FILE *in))
299 {
300         FILE *out;
301         int ret = 0;
302
303         if( (out = fopen(filename, "a")) == NULL )
304                 return 1;
305
306         if( ftell(out) )
307                 return 1;
308
309         ret = (*func) (out);
310         
311         fclose(out);
312         
313         return ret;
314 }
315
316 int
317 fexport(char filtname[FILTNAME_LEN], FILE *handle)
318 {
319         int i;
320
321         for(i=0;; i++) {
322                 if( ! strncmp(e_filters[i].filtname, filtname, FILTNAME_LEN) )
323                         break;
324                 if( ! *e_filters[i].filtname ) {
325                         i = -1;
326                         break;
327                 }
328         }
329
330         return (e_filters[i].func) (handle);
331 }
332
333         
334
335 int
336 export(char filtname[FILTNAME_LEN], char *filename)
337 {
338         int i;
339         int ret = 0;
340         
341         for(i=0;; i++) {
342                 if( ! strncmp(e_filters[i].filtname, filtname, FILTNAME_LEN) )
343                         break;
344                 if( ! *e_filters[i].filtname ) {
345                         i = -1;
346                         break;
347                 }
348         }
349
350         if( i<0 )
351                 return -1;
352
353         if( !strcmp(filename, "-") )
354                 ret = (e_filters[i].func) (stdout);
355         else
356                 ret =  e_write_file(filename, e_filters[i].func);
357
358         return ret;
359 }
360
361 /*
362  * end of common functions
363  */
364
365 /*
366  * ldif import
367  */
368
369 #include "ldif.h"
370
371 static void     ldif_fix_string(char *str);
372
373 #ifndef LINESIZE
374 #       define LINESIZE 1024
375 #endif
376
377 #define LDIF_ITEM_FIELDS        15
378
379 typedef char*  ldif_item[LDIF_ITEM_FIELDS];
380
381 static ldif_item ldif_field_names = {
382         "cn",   
383         "mail",
384         "streetaddress",
385         "locality",
386         "st",
387         "postalcode",
388         "countryname",
389         "homephone",
390         "description",
391         "homeurl",
392         "facsimiletelephonenumber",
393         "cellphone",
394         "xmozillaanyphone",
395         "xmozillanickname",
396         "objectclass", /* this must be the last entry */
397 };
398
399 static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
400         NAME,           /* "cn" */
401         EMAIL,          /* "mail" */
402         ADDRESS,        /* "streetaddress" */
403         CITY,           /* "locality" */
404         STATE,          /* "st" */
405         ZIP,            /* "postalcode" */
406         COUNTRY,        /* "countryname" */
407         PHONE,          /* "homephone" */
408         NOTES,          /* "description" */
409         URL,            /* "homeurl" */
410         FAX,            /* "facsimiletelephonenumber" */
411         MOBILEPHONE,    /* "cellphone" */
412         WORKPHONE,      /* "xmozillaanyphone" */
413         NICK,           /* "xmozillanickname" */
414         -1,             /* "objectclass" */ /* this must be the last entry */
415 };
416
417
418 static char * 
419 ldif_read_line(FILE *in)
420 {
421         char line[LINESIZE];
422         char *buf=NULL;
423         char *ptr, *tmp;
424         long pos;
425         int i;
426
427         for(i=1;;i++) {
428                 pos = ftell(in);
429                 fgets(line, LINESIZE, in);
430                 
431                 if( feof(in) )
432                         break;
433                 
434                 if(i == 1) {
435                         buf = strdup(line);
436                         continue;
437                 }
438                 
439                 if(*line != ' ') {
440                         fseek(in, pos, SEEK_SET);
441                         break;
442                 }
443
444                 ptr = (char *)&line;
445                 while( *ptr == ' ')
446                         ptr++;
447
448                 tmp = buf;
449                 buf = strconcat(buf, ptr, NULL);
450                 free(tmp);
451         }
452
453         if( *buf == '#' ) {
454                 free(buf);
455                 return NULL;
456         }
457                 
458         if(buf) {
459                 int i,j;
460                 for(i=0,j=0; j < strlen(buf); i++, j++)
461                         buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
462         }
463
464         return buf;
465 }
466
467 static void
468 ldif_add_item(ldif_item ldif_item)
469 {
470         list_item abook_item;
471         int i;
472
473         memset(abook_item, 0, sizeof(abook_item));
474         
475         if( !ldif_item[LDIF_ITEM_FIELDS -1] )
476                 goto bail_out;
477         
478
479         for(i=0; i < LDIF_ITEM_FIELDS; i++) {
480                 if(ldif_conv_table[i] >= 0 && ldif_item[i] && *ldif_item[i] )
481                         abook_item[ldif_conv_table[i]] = strdup(ldif_item[i]);
482         }
483
484         add_item2database(abook_item);
485
486 bail_out:
487         for(i=0; i < LDIF_ITEM_FIELDS; i++)
488                 my_free(ldif_item[i]);
489
490 }
491
492 static void
493 ldif_convert(ldif_item item, char *type, char *value)
494 {
495         int i;
496
497         if( !strcmp(type, "dn") ) {
498                 ldif_add_item(item);
499                 return;
500         }
501
502         for(i=0; i < LDIF_ITEM_FIELDS; i++) {
503                 if( !safe_strcmp(ldif_field_names[i], type) && *value ) {
504                         if( i == LDIF_ITEM_FIELDS -1) /* this is a dirty hack */
505                                 if( safe_strcmp("person", value))
506                                         break;
507                         if(item[i])
508                                 my_free(item[i]);
509                         item[i] = strdup(value);
510                 }
511         }
512 }
513
514 static int
515 ldif_parse_file(FILE *handle)
516 {
517         char *line = NULL;
518         char *type, *value;
519         int vlen;
520         ldif_item item;
521
522         memset(item, 0, sizeof(item));
523
524         do {
525                 if( ! (line = ldif_read_line(handle)) )
526                         continue;
527
528                 if( -1 == ( str_parse_line(line, &type, &value, &vlen)) ) {
529                         my_free(line);
530                         continue; /* just skip the errors */
531                 }
532                                 
533                 ldif_fix_string(value);
534
535                 ldif_convert(item, type, value);
536
537                 my_free(line);
538         } while ( !feof(handle) );
539
540         ldif_convert(item, "dn", "");
541
542         return 0;
543 }
544
545 static void
546 ldif_fix_string(char *str)
547 {
548         int i, j;
549
550         for( i = 0, j = 0; j < strlen(str); i++, j++)
551                 str[i] = ( str[j] == (char)0xc3 ?
552                                 (char) str[++j] + (char) 0x40 :
553                                 str[j] );
554
555         str[i] = 0;
556 }
557
558 /*
559  * end of ldif import
560  */
561
562 /*
563  * mutt alias import filter
564  */
565
566 enum {
567         MUTT_ALIAS,
568         MUTT_NAME,
569         MUTT_EMAIL
570 };
571
572 static void
573 remove_newlines(char *buf)
574 {
575         int i,j;
576         
577         for(i=0,j=0; j < strlen(buf); i++, j++)
578                 buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
579 }
580
581 static int
582 mutt_read_line(FILE *in, char **alias, char **rest)
583 {
584         char line[LINESIZE];
585         char *ptr=(char *)&line;
586         char *tmp;
587
588         fgets(line, LINESIZE, in);
589         remove_newlines(line);
590
591         while( ISSPACE(*ptr) )
592                 ptr++;
593
594         if( strncmp("alias", ptr, 5) ) {
595                 return 1;
596         }
597                 
598         ptr += 5;
599
600         while( ISSPACE(*ptr) )
601                 ptr++;
602
603         tmp = ptr;
604
605         while( ! ISSPACE(*ptr) )
606                 ptr++;
607
608         if( (*alias = malloc(ptr-tmp+1)) == NULL)
609                 return 1;
610
611         strncpy(*alias, tmp, ptr-tmp);
612         *(*alias+(ptr-tmp)) = 0;
613
614         while( ISSPACE(*ptr) )
615                 ptr++;
616
617         *rest = strdup(ptr);    
618         
619         return 0;
620 }
621
622 static void
623 mutt_parse_email(char *mutt_item[3])
624 {
625         char *tmp;
626         int i;
627
628         if( (tmp = strchr(mutt_item[MUTT_NAME], '<')) )
629                 *tmp = 0;
630         else
631                 return;
632
633         mutt_item[MUTT_EMAIL] = strdup(tmp+1);
634
635         if( (tmp = strchr(mutt_item[MUTT_EMAIL], '>')) )
636                 *tmp = 0;
637
638         tmp = mutt_item[MUTT_NAME];
639
640         for(i=strlen(tmp)-1; i>0; i--)
641                 if(ISSPACE(tmp[i]))
642                         tmp[i] = 0;
643                 else
644                         break;
645
646         mutt_item[MUTT_NAME] = strdup(tmp);
647
648         free(tmp);
649 }
650
651 static void
652 mutt_add_mutt_item(char *mutt_item[3])
653 {
654         list_item abook_item;
655
656         memset(abook_item, 0, sizeof(abook_item));
657
658         abook_item[NAME] = safe_strdup(mutt_item[MUTT_NAME]);
659         abook_item[EMAIL] = safe_strdup(mutt_item[MUTT_EMAIL]);
660         abook_item[NICK] = safe_strdup(mutt_item[MUTT_ALIAS]);
661
662         add_item2database(abook_item);
663 }
664
665 static int
666 mutt_parse_file(FILE *in)
667 {
668         char *mutt_item[3];
669
670         for(;;) {
671
672                 memset(mutt_item, 0, sizeof(mutt_item) );
673                 
674                 if( mutt_read_line(in, &mutt_item[MUTT_ALIAS],
675                                 &mutt_item[MUTT_NAME]) )
676                         continue;
677
678                 mutt_parse_email(mutt_item);
679
680                 if( feof(in) ) {
681                         free(mutt_item[MUTT_ALIAS]);
682                         free(mutt_item[MUTT_NAME]);
683                         free(mutt_item[MUTT_EMAIL]);
684                         break;
685                 }
686
687                 mutt_add_mutt_item(mutt_item);
688
689                 free(mutt_item[MUTT_ALIAS]);
690                 free(mutt_item[MUTT_NAME]);
691                 free(mutt_item[MUTT_EMAIL]);
692         }
693
694
695         return 0;
696 }
697
698 /*
699  * end of mutt alias import filter
700  */
701
702 /*
703  * ldif export filter
704  */
705
706 static void
707 ldif_fput_type_and_value(FILE *out,char *type, char *value )
708 {
709         char *tmp;
710
711         tmp = ldif_type_and_value(type, value, strlen(value));
712
713         fputs(tmp, out);
714
715         free(tmp);
716 }
717
718 static int
719 ldif_export_database(FILE *out)
720 {
721         int i;
722         char email[MAX_EMAILSTR_LEN];
723
724         fprintf(out, "version: 1\n");
725         for(i=0; i<items; i++) {
726                 char *tmp;
727                 int j;
728                 get_first_email(email, i);
729
730                 tmp = mkstr("cn=%s,mail=%s", database[i][NAME], email);
731                 ldif_fput_type_and_value(out, "dn", tmp);
732                 free(tmp);
733
734                 for(j=0; j < LDIF_ITEM_FIELDS; j++) {
735                         if(ldif_conv_table[j] >= 0) {
736                                 if(ldif_conv_table[j] == EMAIL)
737                                         ldif_fput_type_and_value(out,
738                                                 ldif_field_names[j], email);
739                                 else if(database[i][ldif_conv_table[j]])
740                                         ldif_fput_type_and_value(out,
741                                                 ldif_field_names[j],
742                                                 database[i][ldif_conv_table[j]]);
743                         }
744                 }
745
746                 fprintf(out, "objectclass: top\n"
747                                 "objectclass: person\n\n");
748         }
749
750         return 0;
751 }
752
753 /*
754  * end of ldif export filter
755  */
756
757 /*
758  * html export filter
759  */
760
761 static void            html_export_write_head(FILE *out, int extra_column);
762 static void            html_export_write_tail(FILE *out);
763
764 static int
765 html_export_database(FILE *out)
766 {
767         char tmp[MAX_EMAILSTR_LEN];
768         int i;
769         int extra_column = options_get_int("extra_column");
770
771         if( items < 1 )
772                 return 2;
773
774         extra_column = (extra_column > 2 && extra_column < ITEM_FIELDS) ?
775                 extra_column : PHONE;
776
777         html_export_write_head(out, extra_column);
778         for( i = 0; i < items; i++ ) {
779                 get_first_email(tmp, i);
780                 fprintf(out, "<tr>\n<td><a href=\"mailto:%s\">%s</a>\n",
781                                 tmp,
782                                 database[i][NAME] );
783                                 
784                 fprintf(out, "<td>%s\n<td>%s\n",
785                                 database[i][EMAIL],
786                                 safe_str(database[i][extra_column]) );
787                 fprintf(out, "</tr>\n\n");
788         }
789         html_export_write_tail(out);
790
791         return 0;
792 }
793
794
795 static void
796 html_export_write_head(FILE *out, int extra_column)
797 {
798         char *realname = get_real_name();
799
800         fprintf(out, "<html>\n<head>\n  <title>%s's addressbook</title>",
801                         realname );
802         fprintf(out, "\n</head>\n<body>\n");
803         fprintf(out, "\n<h2>%s's addressbook</h2>\n", realname );
804         fprintf(out, "<br><br>\n\n");
805
806         fprintf(out, "<center><table border>\n");
807         fprintf(out, "\n<tr><th>Name<th>E-mail address(es)<th>%s</tr>\n\n",
808                         abook_fields[extra_column].name);
809
810         free(realname);
811 }
812
813 static void
814 html_export_write_tail(FILE *out)
815 {
816         fprintf(out, "\n</table></center>\n");
817         fprintf(out, "\n</body>\n</html>\n");
818 }
819         
820 /*
821  * end of html export filter
822  */
823
824 /*
825  * pine addressbook import filter
826  */
827
828 static void
829 pine_fixbuf(char *buf)
830 {
831         int i,j;
832
833         for(i=0,j=0; j < strlen(buf); i++, j++)
834                 buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
835 }
836
837 static void
838 pine_convert_emails(char *s)
839 {
840         int i;
841         char *tmp;
842
843         if( s == NULL || *s != '(' )
844                 return;
845
846         for(i=0; s[i]; i++ )
847                 s[i] = s[i+1];
848
849         if( ( tmp = strchr(s,')')) )
850                 *tmp=0;
851         
852         for(i=1; ( tmp = strchr(s, ',') ) != NULL ; i++, s=tmp+1 )
853                 if( i > 3 ) {
854                         *tmp = 0;
855                         break;  
856                 }
857
858 }
859
860 static void
861 pine_parse_buf(char *buf)
862 {
863         list_item item;
864         char *start = buf;
865         char *end;
866         char tmp[400];
867         int i, len, last;
868         int pine_conv_table[]= {NICK, NAME, EMAIL, -1, NOTES};
869
870         memset(&item, 0, sizeof(item) );
871         
872         for(i=0, last=0; !last ; i++) {
873                 if( ! (end = strchr(start, '\t')) )
874                         last=1;
875                 
876                 len = last ? strlen(start) : (int) (end-start);
877                 len = min(len, 400-1);
878         
879                 if(i < sizeof(pine_conv_table) / sizeof(*pine_conv_table)
880                                 && pine_conv_table[i] >= 0) {
881                         strncpy(tmp, start, len);
882                         tmp[len] = 0;
883                         item[pine_conv_table[i]] = strdup(tmp);
884                 }
885                 start = end + 1;
886         }
887         
888         pine_convert_emails(item[EMAIL]);
889         add_item2database(item);
890 }
891                 
892
893 #define LINESIZE        1024
894
895 static int
896 pine_parse_file(FILE *in)
897 {
898         char line[LINESIZE];
899         char *buf=NULL;
900         char *ptr;
901         int i;
902
903         fgets(line, LINESIZE, in);      
904         
905         while(!feof(in)) {
906                 for(i=2;;i++) {
907                         buf = realloc(buf, i*LINESIZE);
908                         if(i==2)
909                                 strcpy(buf, line);
910                         fgets(line, LINESIZE, in);
911                         ptr=(char *)&line;
912                         if(*ptr != ' ' || feof(in) )
913                                 break;
914                         else
915                                 while( *ptr == ' ') ptr++;
916                                 
917                         strcat(buf, ptr);
918                 }
919                 if( *buf == '#' )
920                         continue;
921                 pine_fixbuf(buf);
922
923                 pine_parse_buf(buf);
924
925                 my_free(buf);
926         }
927
928         return 0;
929 }
930
931 /*
932  * end of pine addressbook import filter
933  */
934
935 /*
936  * pine addressbook export filter
937  *
938  *  filter doesn't wrap the lines as it should but Pine seems to handle
939  *  created files without problems - JH
940  */
941
942 static int
943 pine_export_database(FILE *out)
944 {
945         int i;
946
947         for(i=0; i < items; i++ ) {
948                 fprintf(out, have_multiple_emails(i) ?
949                                 "%s\t%s\t(%s)\t\t%s\n" : "%s\t%s\t%s\t\t%s\n",
950                                 safe_str(database[i][NICK]),
951                                 safe_str(database[i][NAME]),
952                                 safe_str(database[i][EMAIL]),
953                                 safe_str(database[i][NOTES])
954                                 );
955         }
956
957         return 0;
958 }
959
960 /*
961  * end of pine addressbook export filter
962  */
963
964
965 /*
966  * csv addressbook export filter
967  */
968
969 static int
970 csv_export_database(FILE *out)
971 {
972         int i, j;
973         int csv_export_fields[] = {
974                 NAME,
975                 EMAIL,
976                 PHONE,
977                 NOTES,
978                 -1
979         };
980
981         for(i=0; i < items; i++ ) {
982                 for(j = 0; csv_export_fields[j] >= 0; j++) {
983                         fprintf(out, strchr(safe_str(database[i][csv_export_fields[j]]), ',') ?
984                                 "\"%s\"" : "%s",
985                                 safe_str(database[i][csv_export_fields[j]])
986                                 );
987                         if(csv_export_fields[j+1] >= 0)
988                                 fputc(',', out);
989                 }
990                 fputc('\n', out);
991         }
992                 
993
994
995         return 0;
996 }
997
998 /*
999  * end of csv export filter
1000  */
1001
1002
1003 /*
1004  * GnomeCard (VCard) addressbook export filter
1005  */
1006
1007 static int
1008 gcrd_export_database(FILE *out)
1009 {
1010         char emails[MAX_EMAILS][MAX_EMAIL_LEN];
1011         int i, j;
1012         char *name;
1013
1014         for(i=0; i < items; i++ ) {
1015                 fprintf(out, "BEGIN:VCARD\nFN:%s\n",
1016                                 safe_str(database[i][NAME]));
1017
1018                 name = get_surname(database[i][NAME]);
1019                 for( j = strlen(database[i][NAME]) - 1; j >= 0; j-- ) {
1020                         if(database[i][NAME][j] == ' ')
1021                                 break;
1022                 } 
1023                 fprintf(out, "N:%s;%.*s\n",
1024                         safe_str(name),
1025                         j,
1026                         safe_str(database[i][NAME])
1027                         ); 
1028
1029                 free(name);
1030
1031                 if ( database[i][ADDRESS] )
1032                         fprintf(out, "ADR:;;%s;%s;%s;%s;%s\n",
1033                                 safe_str(database[i][ADDRESS]),
1034                                 safe_str(database[i][CITY]),
1035                                 safe_str(database[i][STATE]),
1036                                 safe_str(database[i][ZIP]),
1037                                 safe_str(database[i][COUNTRY])
1038                                 );
1039                 
1040                 if (database[i][PHONE])
1041                         fprintf(out, "TEL;HOME:%s\n", database[i][PHONE]);
1042                 if (database[i][WORKPHONE])
1043                         fprintf(out, "TEL;WORK:%s\n", database[i][WORKPHONE]);
1044                 if (database[i][FAX])
1045                         fprintf(out, "TEL;FAX:%s\n", database[i][FAX]);
1046                 if (database[i][MOBILEPHONE])
1047                         fprintf(out, "TEL;CELL:%s\n", database[i][MOBILEPHONE]);
1048
1049                 if ( database[i][EMAIL] ) {
1050                         split_emailstr(i, emails);
1051                         for(j=0; j < MAX_EMAILS ; j++) {
1052                                 if ( *emails[j] ) 
1053                                         fprintf(out, "EMAIL;INTERNET:%s\n",
1054                                                 emails[j]);
1055                         }
1056                 }
1057                 
1058                 if ( database[i][NOTES] ) 
1059                         fprintf(out, "NOTE:%s\n", database[i][NOTES]);
1060                 if (database[i][URL])
1061                         fprintf(out, "URL:%s\n",  database[i][URL]);
1062
1063                 fprintf(out, "END:VCARD\n\n");
1064                 
1065         }
1066
1067         return 0;
1068 }
1069
1070 /*
1071  * end of GnomeCard export filter
1072  */
1073
1074
1075 /*
1076  * mutt alias export filter
1077  */
1078
1079 static char *
1080 mutt_alias_genalias(int i)
1081 {
1082         char *tmp, *pos;
1083         
1084         if(database[i][NICK])
1085                 return strdup(database[i][NICK]);
1086
1087         tmp = strdup(database[i][NAME]);
1088
1089         if( ( pos = strchr(tmp, ' ') ) )
1090                 *pos = 0;
1091
1092         strlower(tmp);
1093
1094         return tmp;     
1095 }
1096
1097 static int
1098 mutt_alias_export(FILE *out)
1099 {
1100         int i;
1101         char email[MAX_EMAIL_LEN];
1102         char *alias = NULL;
1103
1104         for(i=0; i<items; i++) {
1105                 alias = mutt_alias_genalias(i);
1106
1107                 get_first_email(email, i);
1108                 fprintf(out, *email ? "alias %s %s <%s>\n": "alias %s %s%s\n",
1109                                 alias,
1110                                 database[i][NAME],
1111                                 email);
1112                 my_free(alias);
1113         }
1114
1115         return 0;
1116 }
1117
1118 /*
1119  * end of mutt alias export filter
1120  */
1121
1122
1123 /*
1124  * printable export filter
1125  */
1126
1127 static int
1128 text_export_database(FILE * out)
1129 {
1130         char emails[MAX_EMAILS][MAX_EMAIL_LEN];
1131         int i, j;
1132         char *realname = get_real_name();
1133         char *style = options_get_str("address_style");
1134
1135         fprintf(out,
1136                 "-----------------------------------------\n%s's address book\n"
1137                 "-----------------------------------------\n\n\n",
1138                 realname);
1139         free(realname);
1140
1141         for (i = 0; i < items; i++) {
1142                 fprintf(out,
1143                         "-----------------------------------------\n\n");
1144                 fprintf(out, "%s", database[i][NAME]);
1145                 if (database[i][NICK])
1146                         fprintf(out, "\n(%s)", database[i][NICK]);
1147                 fprintf(out, "\n");
1148
1149                 if (*database[i][EMAIL]) {
1150                         fprintf(out, "\n");
1151                         split_emailstr(i, emails);
1152                         for (j = 0; j < MAX_EMAILS; j++)
1153                                 if (*emails[j])
1154                                         fprintf(out, "%s\n", emails[j]);
1155                 }
1156                 /* Print address */
1157                 if (database[i][ADDRESS]) {
1158                         if (!safe_strcmp(style, "us")) {        /* US like */
1159                                 fprintf(out, "\n%s", database[i][ADDRESS]);
1160                                 if (database[i][CITY])
1161                                         fprintf(out, "\n%s",
1162                                                 database[i][CITY]);
1163                                 if (database[i][STATE] || database[i][ZIP])
1164                                         fprintf(out, "\n%s %s",
1165                                                 safe_str(database[i]
1166                                                          [STATE]),
1167                                                 safe_str(database[i]
1168                                                          [ZIP]));
1169                                 if (database[i][COUNTRY])
1170                                         fprintf(out, "\n%s",
1171                                                 database[i][COUNTRY]);
1172                         }
1173
1174                         else if (!safe_strcmp(style, "uk")) {   /* UK like */
1175                                 for (j = ADDRESS; j <= COUNTRY; j++)
1176                                         if (database[i][j])
1177                                                 fprintf(out, "\n%s",
1178                                                         database[i][j]);
1179                         } else {        /* EU like */
1180                                 fprintf(out, "\n%s", database[i][ADDRESS]);
1181                                 if (database[i][ZIP] || database[i][CITY])
1182                                         fprintf(out, "\n%s %s",
1183                                                 safe_str(database[i][ZIP]),
1184                                                 safe_str(database[i]
1185                                                          [CITY]));
1186                                 if (database[i][STATE])
1187                                         fprintf(out, "\n%s",
1188                                                 database[i][STATE]);
1189                                 if (database[i][COUNTRY])
1190                                         fprintf(out, "\n%s",
1191                                                 database[i][COUNTRY]);
1192                         }
1193
1194                         fprintf(out, "\n");
1195                 }
1196
1197                 if ((database[i][PHONE]) || (database[i][WORKPHONE]) ||
1198                     (database[i][FAX]) || (database[i][MOBILEPHONE])) {
1199                         fprintf(out, "\n");
1200                         for (j = PHONE; j <= MOBILEPHONE; j++)
1201                                 if (database[i][j])
1202                                         fprintf(out, "%s: %s\n",
1203                                                 abook_fields[j].name,
1204                                                 database[i][j]);
1205                 }
1206
1207                 if (database[i][URL])
1208                         fprintf(out, "\n%s\n", database[i][URL]);
1209                 if (database[i][NOTES])
1210                         fprintf(out, "\n%s\n", database[i][NOTES]);
1211
1212                 fprintf(out, "\n");
1213         }
1214
1215         fprintf(out, "-----------------------------------------\n");
1216
1217         return 0;
1218 }
1219
1220 /*
1221  * end of printable export filter
1222  */
1223
1224 /*
1225  * elm alias export filter
1226  */
1227
1228 static int
1229 elm_alias_export(FILE *out)
1230 {
1231         int i;
1232         char email[MAX_EMAIL_LEN];
1233         char *alias = NULL;
1234
1235         for(i=0; i<items; i++) {
1236                 alias = mutt_alias_genalias(i);
1237                 get_first_email(email, i);
1238                 fprintf(out, "%s = %s = %s\n",
1239                                 alias,
1240                                 database[i][NAME],
1241                                 email);
1242                 my_free(alias);
1243         }
1244
1245         return 0;
1246 }
1247
1248 /*
1249  * end of elm alias export filter
1250  */
1251
1252
1253 /*
1254  * Spruce export filter
1255  */
1256
1257 static int
1258 spruce_export_database (FILE *out)
1259 {
1260         int i;
1261         char email[MAX_EMAIL_LEN];
1262
1263         fprintf (out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
1264
1265         for (i= 0; i< items; i++) {
1266                 if(strcmp (safe_str(database[i][EMAIL]), "")) {
1267                         get_first_email(email, i);
1268                         fprintf(out, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
1269                                         i,
1270                                         database[i][NAME],
1271                                         email,
1272                                         safe_str(database[i][NOTES])
1273                                         );
1274                 }
1275         }
1276
1277         fprintf (out, "# End of address book file.\n");
1278
1279         return 0;
1280 }
1281
1282 /*
1283  * end of Spruce export filter
1284  */
1285