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