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