3 * $Id: filter.c,v 1.55 2006/09/06 02:46:44 cduval Exp $
5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
16 #include <sys/types.h>
17 #include "abook_curses.h"
30 extern abook_field_list
*fields_list
;
31 extern int fields_count
;
34 * function declarations
38 * import filter prototypes
41 static int ldif_parse_file(FILE *handle
);
42 static int mutt_parse_file(FILE *in
);
43 static int pine_parse_file(FILE *in
);
44 static int csv_parse_file(FILE *in
);
45 static int allcsv_parse_file(FILE *in
);
46 static int palmcsv_parse_file(FILE *in
);
47 static int vcard_parse_file(FILE *in
);
50 * export filter prototypes
53 static int ldif_export_database(FILE *out
, struct db_enumerator e
);
54 static int html_export_database(FILE *out
, struct db_enumerator e
);
55 static int pine_export_database(FILE *out
, struct db_enumerator e
);
56 static int csv_export_database(FILE *out
, struct db_enumerator e
);
57 static int allcsv_export_database(FILE *out
, struct db_enumerator e
);
58 static int palm_export_database(FILE *out
, struct db_enumerator e
);
59 static int gcrd_export_database(FILE *out
, struct db_enumerator e
);
60 static int mutt_alias_export(FILE *out
, struct db_enumerator e
);
61 static int elm_alias_export(FILE *out
, struct db_enumerator e
);
62 static int text_export_database(FILE *out
, struct db_enumerator e
);
63 static int spruce_export_database(FILE *out
, struct db_enumerator e
);
64 static int wl_export_database(FILE *out
, struct db_enumerator e
);
65 static int bsdcal_export_database(FILE *out
, struct db_enumerator e
);
68 * end of function declarations
71 struct abook_input_filter i_filters
[] = {
72 { "abook", N_("abook native format"), parse_database
},
73 { "ldif", N_("ldif / Netscape addressbook"), ldif_parse_file
},
74 { "mutt", N_("mutt alias"), mutt_parse_file
},
75 { "pine", N_("pine addressbook"), pine_parse_file
},
76 { "csv", N_("comma separated values"), csv_parse_file
},
77 { "allcsv", N_("comma separated values (all fields)"), allcsv_parse_file
},
78 { "palmcsv", N_("Palm comma separated values"), palmcsv_parse_file
},
79 { "vcard", N_("vCard file"), vcard_parse_file
},
83 struct abook_output_filter e_filters
[] = {
84 { "abook", N_("abook native format"), write_database
},
85 { "ldif", N_("ldif / Netscape addressbook (.4ld)"), ldif_export_database
},
86 { "mutt", N_("mutt alias"), mutt_alias_export
},
87 { "html", N_("html document"), html_export_database
},
88 { "pine", N_("pine addressbook"), pine_export_database
},
89 { "gcrd", N_("GnomeCard (VCard) addressbook"), gcrd_export_database
},
90 { "csv", N_("comma separated values"), csv_export_database
},
91 { "allcsv", N_("comma separated values (all fields)"), allcsv_export_database
},
92 { "palmcsv", N_("Palm comma separated values"), palm_export_database
},
93 { "elm", N_("elm alias"), elm_alias_export
},
94 { "text", N_("plain text"), text_export_database
},
95 { "wl", N_("Wanderlust address book"), wl_export_database
},
96 { "spruce", N_("Spruce address book"), spruce_export_database
},
97 { "bsdcal", N_("BSD calendar"), bsdcal_export_database
},
111 for(i
=0; *i_filters
[i
].filtname
; i
++)
112 printf("\t%s\t%s\n", i_filters
[i
].filtname
,
113 gettext(i_filters
[i
].desc
));
118 for(i
=0; *e_filters
[i
].filtname
; i
++)
119 printf("\t%s\t%s\n", e_filters
[i
].filtname
,
120 gettext(e_filters
[i
].desc
));
126 number_of_output_filters()
130 for(i
=0; *e_filters
[i
].filtname
; i
++)
137 number_of_input_filters()
141 for(i
=0; *i_filters
[i
].filtname
; i
++)
150 char *username
= getenv("USER");
151 struct passwd
*pwent
;
155 pwent
= getpwnam(username
);
157 if((tmp
= xstrdup(pwent
->pw_gecos
)) == NULL
)
158 return xstrdup(username
);
160 rtn
= sscanf(pwent
->pw_gecos
, "%[^,]", tmp
);
161 if (rtn
== EOF
|| rtn
== 0) {
163 return xstrdup(username
);
172 static int i_read_file(char *filename
, int (*func
) (FILE *in
));
181 refresh_statusline();
182 headerline(_("import database"));
184 mvaddstr(3, 1, _("please select a filter"));
187 for(i
=0; *i_filters
[i
].filtname
; i
++)
188 mvprintw(5 + i
, 6, "%c -\t%s\t%s\n", 'a' + i
,
189 i_filters
[i
].filtname
,
190 gettext(i_filters
[i
].desc
));
192 mvprintw(6 + i
, 6, _("x -\tcancel"));
200 int tmp
= db_n_items();
204 filter
= getch() - 'a';
205 if(filter
== 'x' - 'a' ||
206 filter
>= number_of_input_filters() || filter
< 0) {
211 mvaddstr(5+filter
, 2, "->");
213 filename
= ask_filename(_("Filename: "));
219 if(i_read_file(filename
, i_filters
[filter
].func
))
220 statusline_msg(_("Error occured while opening the file"));
221 else if(tmp
== db_n_items())
222 statusline_msg(_("File does not seem to be a valid addressbook"));
233 i_read_file(char *filename
, int (*func
) (FILE *in
))
238 if( (in
= abook_fopen( filename
, "r" )) == NULL
)
249 import_file(char filtname
[FILTNAME_LEN
], char *filename
)
252 int tmp
= db_n_items();
256 if(! strncasecmp(i_filters
[i
].filtname
, filtname
,
259 if(! *i_filters
[i
].filtname
) {
268 if(!strcmp(filename
, "-")) {
270 if((fstat(fileno(stdin
), &s
)) == -1 || S_ISDIR(s
.st_mode
))
273 ret
= (*i_filters
[i
].func
) (stdin
);
275 ret
= i_read_file(filename
, i_filters
[i
].func
);
277 if(tmp
== db_n_items())
287 static int e_write_file(char *filename
,
288 int (*func
) (FILE *in
, struct db_enumerator e
), int mode
);
298 refresh_statusline();
299 headerline(_("export database"));
301 mvaddstr(3, 1, _("please select a filter"));
304 for(i
= 0; *e_filters
[i
].filtname
; i
++)
305 mvprintw(5 + i
, 6, "%c -\t%s\t%s\n", 'a' + i
,
306 e_filters
[i
].filtname
,
307 gettext(e_filters
[i
].desc
));
309 mvprintw(6 + i
, 6, _("x -\tcancel"));
316 int enum_mode
= ENUM_ALL
;
321 filter
= getch() - 'a';
322 if(filter
== 'x' - 'a' ||
323 filter
>= number_of_output_filters() || filter
< 0) {
328 mvaddstr(5 + filter
, 2, "->");
330 if(selected_items()) {
331 switch(statusline_askchoice(
332 _("Export <a>ll, export <s>elected, or <c>ancel?"),
333 S_("keybindings:all/selected/cancel|asc"), 3)) {
337 enum_mode
= ENUM_SELECTED
;
347 filename
= ask_filename(_("Filename: "));
353 if( e_write_file(filename
, e_filters
[filter
].func
, enum_mode
))
354 statusline_msg(_("Error occured while exporting"));
363 e_write_file(char *filename
, int (*func
) (FILE *in
, struct db_enumerator e
),
368 struct db_enumerator enumerator
= init_db_enumerator(mode
);
370 if((out
= fopen(filename
, "a")) == NULL
)
376 ret
= (*func
) (out
, enumerator
);
384 fexport(char filtname
[FILTNAME_LEN
], FILE *handle
, int enum_mode
)
387 struct db_enumerator e
= init_db_enumerator(enum_mode
);
390 if(!strncasecmp(e_filters
[i
].filtname
, filtname
,
393 if(!*e_filters
[i
].filtname
) {
399 return (e_filters
[i
].func
) (handle
, e
);
405 export_file(char filtname
[FILTNAME_LEN
], char *filename
)
407 const int mode
= ENUM_ALL
;
410 struct db_enumerator e
= init_db_enumerator(mode
);
413 if(!strncasecmp(e_filters
[i
].filtname
, filtname
,
416 if(!*e_filters
[i
].filtname
) {
425 if(!strcmp(filename
, "-"))
426 ret
= (e_filters
[i
].func
) (stdout
, e
);
428 ret
= e_write_file(filename
, e_filters
[i
].func
, mode
);
434 * end of common functions
443 static void ldif_fix_string(char *str
);
445 #define LDIF_ITEM_FIELDS 16
447 typedef char *ldif_item
[LDIF_ITEM_FIELDS
];
449 static ldif_item ldif_field_names
= {
461 "facsimiletelephonenumber",
465 "objectclass", /* this must be the last entry */
468 static int ldif_conv_table
[LDIF_ITEM_FIELDS
] = {
471 ADDRESS
, /* "streetaddress" */
472 ADDRESS2
, /* "streetaddress2" */
473 CITY
, /* "locality" */
475 ZIP
, /* "postalcode" */
476 COUNTRY
, /* "countryname" */
477 PHONE
, /* "homephone" */
478 NOTES
, /* "description" */
480 FAX
, /* "facsimiletelephonenumber" */
481 MOBILEPHONE
, /* "cellphone" */
482 WORKPHONE
, /* "xmozillaanyphone" */
483 NICK
, /* "xmozillanickname" */
484 -1, /* "objectclass" */ /* this must be the last entry */
489 ldif_read_line(FILE *in
)
502 if(feof(in
) || !line
)
511 fseek(in
, pos
, SEEK_SET
); /* fixme ! */
521 buf
= strconcat(buf
, ptr
, NULL
);
526 if(buf
&& *buf
== '#' ) {
535 ldif_add_item(ldif_item li
)
540 item
= item_create();
542 if(!li
[LDIF_ITEM_FIELDS
-1])
546 for(i
=0; i
< LDIF_ITEM_FIELDS
; i
++) {
547 if(ldif_conv_table
[i
] >= 0 && li
[i
] && *li
[i
])
548 item_fput(item
,ldif_conv_table
[i
],xstrdup(li
[i
]));
551 add_item2database(item
);
554 for(i
=0; i
< LDIF_ITEM_FIELDS
; i
++)
561 ldif_convert(ldif_item item
, char *type
, char *value
)
565 if(!strcmp(type
, "dn")) {
570 for(i
=0; i
< LDIF_ITEM_FIELDS
; i
++) {
571 if(!safe_strcmp(ldif_field_names
[i
], type
) && *value
) {
572 if(i
== LDIF_ITEM_FIELDS
- 1) /* this is a dirty hack */
573 if(safe_strcmp("person", value
))
576 if(item_fget(item
, i
))
577 free(item_fget(item
, i
));
579 item_fput(item
, i
, xstrdup(value
));
585 ldif_parse_file(FILE *handle
)
592 memset(item
, 0, sizeof(item
));
595 if( !(line
= ldif_read_line(handle
)) )
598 if(-1 == (str_parse_line(line
, &type
, &value
, &vlen
))) {
600 continue; /* just skip the errors */
603 ldif_fix_string(value
);
605 ldif_convert(item
, type
, value
);
608 } while ( !feof(handle
) );
610 ldif_convert(item
, "dn", "");
616 ldif_fix_string(char *str
)
620 for(i
= 0, j
= 0; j
< (int)strlen(str
); i
++, j
++)
621 str
[i
] = ( str
[j
] == (char)0xc3 ?
622 (char) str
[++j
] + (char) 0x40 :
633 * mutt alias import filter
639 mutt_read_line(FILE *in
, char **alias
, char **rest
)
641 char *line
, *ptr
, *tmp
;
644 if( !(line
= ptr
= getaline(in
)) )
645 return 1; /* error / EOF */
649 if(strncmp("alias", ptr
, 5)) {
660 while( ! ISSPACE(*ptr
) )
663 alias_len
= (size_t)(ptr
- tmp
);
666 *alias
= xmalloc_inc(alias_len
, 1);
668 strncpy(*alias
, tmp
, alias_len
);
669 *(*alias
+ alias_len
) = 0;
673 *rest
= xstrdup(ptr
);
680 mutt_fix_quoting(char *p
)
700 mutt_parse_email(list_item item
)
702 char *line
= item_fget(item
, NAME
);
710 mutt_fix_quoting(line
);
711 tmp
= strconcat("From: ", line
, NULL
);
712 getname(tmp
, &name
, &email
);
716 item_fput(item
, NAME
, name
);
721 item_fput(item
, EMAIL
, email
);
726 * this is completely broken
729 while( (start
= strchr(start
, ',')) && i
++ < MAX_EMAILS
- 1) {
730 tmp
= strconcat("From: ", ++start
, NULL
);
731 getname(tmp
, &name
, &email
);
736 tmp
= strconcat(item
[EMAIL
], ",", email
, NULL
);
748 mutt_parse_file(FILE *in
)
750 list_item item
= item_create();
753 memset(item
, 0, fields_count
* sizeof(char *));
755 if(!mutt_read_line(in
,
756 (field_id(NICK
) != -1) ?
757 &item
[field_id(NICK
)] : NULL
,
758 &item
[field_id(NAME
)]))
759 mutt_parse_email(item
);
766 add_item2database(item
);
774 * end of mutt alias import filter
783 ldif_fput_type_and_value(FILE *out
,char *type
, char *value
)
787 tmp
= ldif_type_and_value(type
, value
, strlen(value
));
795 ldif_export_database(FILE *out
, struct db_enumerator e
)
797 char email
[MAX_EMAILSTR_LEN
];
799 fprintf(out
, "version: 1\n");
801 db_enumerate_items(e
) {
804 get_first_email(email
, e
.item
);
806 tmp
= strdup_printf("cn=%s,mail=%s",db_name_get(e
.item
),email
);
808 ldif_fput_type_and_value(out
, "dn", tmp
);
811 for(j
= 0; j
< LDIF_ITEM_FIELDS
; j
++) {
812 if(ldif_conv_table
[j
] >= 0) {
813 if(ldif_conv_table
[j
] == EMAIL
)
814 ldif_fput_type_and_value(out
,
815 ldif_field_names
[j
], email
);
816 else if(db_fget(e
.item
,ldif_conv_table
[j
]))
817 ldif_fput_type_and_value(out
,
820 ldif_conv_table
[j
]));
824 fprintf(out
, "objectclass: top\n"
825 "objectclass: person\n\n");
832 * end of ldif export filter
839 static void html_export_write_head(FILE *out
);
840 static void html_export_write_tail(FILE *out
);
842 extern struct index_elem
*index_elements
;
845 html_print_emails(FILE *out
, struct list_field
*f
)
847 abook_list
*l
= csv_to_abook_list(f
->data
);
849 for(; l
; l
= l
->next
) {
850 fprintf(out
, "<a href=\"mailto:%s\">%s</a>", l
->data
, l
->data
);
859 html_export_database(FILE *out
, struct db_enumerator e
)
862 struct index_elem
*cur
;
869 html_export_write_head(out
);
871 db_enumerate_items(e
) {
872 fprintf(out
, "<tr>");
873 for(cur
= index_elements
; cur
; cur
= cur
->next
) {
874 if(cur
->type
!= INDEX_FIELD
)
877 get_list_field(e
.item
, cur
, &f
);
879 if(f
.type
== FIELD_EMAILS
) {
880 fprintf(out
, "<td>");
881 html_print_emails(out
, &f
);
882 fprintf(out
, "</td>");
885 fprintf(out
, "<td>%s</td>", safe_str(f
.data
));
888 fprintf(out
, "</tr>\n");
891 html_export_write_tail(out
);
897 html_export_write_head(FILE *out
)
899 char *realname
= get_real_name(), *str
;
900 struct index_elem
*cur
;
902 fprintf(out
, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
903 fprintf(out
, "<html>\n<head>\n <title>%s's addressbook</title>",
905 fprintf(out
, "\n</head>\n<body>\n");
906 fprintf(out
, "\n<h2>%s's addressbook</h2>\n", realname
);
907 fprintf(out
, "<br><br>\n\n");
909 fprintf(out
, "<table border=\"1\" align=\"center\">\n<tr>");
910 for(cur
= index_elements
; cur
; cur
= cur
->next
) {
911 if(cur
->type
!= INDEX_FIELD
)
914 get_field_info(cur
->d
.field
.id
, NULL
, &str
, NULL
);
915 fprintf(out
, "<th>%s</th>", str
);
917 fprintf(out
, "</tr>\n\n");
923 html_export_write_tail(FILE *out
)
925 fprintf(out
, "\n</table>\n");
926 fprintf(out
, "\n</body>\n</html>\n");
930 * end of html export filter
935 * pine addressbook import filter
938 #define PINE_BUF_SIZE 2048
941 pine_fixbuf(char *buf
)
945 for(i
= 0,j
= 0; j
< (int)strlen(buf
); i
++, j
++)
946 buf
[i
] = buf
[j
] == '\n' ? buf
[++j
] : buf
[j
];
950 pine_convert_emails(char *s
)
955 if(s
== NULL
|| *s
!= '(')
958 for(i
= 0; s
[i
]; i
++)
961 if( ( tmp
= strchr(s
,')')) )
964 for(i
= 1; ( tmp
= strchr(s
, ',') ) != NULL
; i
++, s
= tmp
+ 1)
965 if(i
> MAX_LIST_ITEMS
- 1) {
973 pine_parse_buf(char *buf
)
978 char tmp
[PINE_BUF_SIZE
];
980 int pine_conv_table
[]= {NICK
, NAME
, EMAIL
, -1, NOTES
};
982 item
= item_create();
984 for(i
=0, last
=0; !last
; i
++) {
985 if( !(end
= strchr(start
, '\t')) )
988 len
= last
? strlen(start
) : (int) (end
-start
);
989 len
= min(len
, PINE_BUF_SIZE
- 1);
991 if(i
< (int)(sizeof(pine_conv_table
) / sizeof(*pine_conv_table
))
992 && pine_conv_table
[i
] >= 0) {
993 strncpy(tmp
, start
, len
);
996 item_fput(item
, pine_conv_table
[i
],
1002 pine_convert_emails(item_fget(item
, EMAIL
));
1003 add_item2database(item
);
1008 #define LINESIZE 1024
1011 pine_parse_file(FILE *in
)
1013 char line
[LINESIZE
];
1018 fgets(line
, LINESIZE
, in
);
1022 buf
= xrealloc(buf
, i
*LINESIZE
);
1025 fgets(line
, LINESIZE
, in
);
1027 if(*ptr
!= ' ' || feof(in
))
1041 pine_parse_buf(buf
);
1050 * end of pine addressbook import filter
1055 * pine addressbook export filter
1057 * filter doesn't wrap the lines as it should but Pine seems to handle
1058 * created files without problems - JH
1062 pine_export_database(FILE *out
, struct db_enumerator e
)
1066 db_enumerate_items(e
) {
1067 emails
= db_email_get(e
.item
);
1068 fprintf(out
, strchr(emails
, ',') /* multiple addresses? */ ?
1069 "%s\t%s\t(%s)\t\t%s\n" : "%s\t%s\t%s\t\t%s\n",
1070 safe_str(db_fget(e
.item
, NICK
)),
1071 safe_str(db_name_get(e
.item
)),
1073 safe_str(db_fget(e
.item
, NOTES
))
1082 * end of pine addressbook export filter
1091 * these files should be parsed according to a certain
1092 * lay out, or the default if layout is not given, at
1093 * the moment only default is done...
1096 #define CSV_COMMENT_CHAR '#'
1097 #define CSV_DUPLICATE_SEPARATOR " "
1098 #define CSV_TABLE_SIZE(t) (sizeof (t) / sizeof *(t))
1100 static int csv_conv_table
[] = {
1108 static int allcsv_conv_table
[] = {
1127 static int palmcsv_conv_table
[] = {
1128 NAME
, /* Last name */
1129 NAME
, /* First name */
1146 csv_convert_emails(char *s
)
1154 for(i
= 1; ( tmp
= strchr(s
, ',') ) != NULL
; i
++, s
= tmp
+ 1)
1155 if(i
> MAX_LIST_ITEMS
- 1) {
1163 csv_remove_quotes(char *s
)
1165 char *copy
, *trimmed
;
1168 copy
= trimmed
= xstrdup(s
);
1171 len
= strlen(trimmed
);
1172 if(trimmed
[len
- 1] == '\"' && *trimmed
== '\"') {
1177 trimmed
[len
- 1] = 0;
1179 trimmed
= xstrdup(trimmed
);
1189 csv_field_to_item(int *table_base
, size_t table_size
, int field
)
1191 if(field
< table_size
)
1192 return field_id(table_base
[field
]);
1198 csv_store_item(list_item item
, int i
, char *s
)
1200 char *newstr
= NULL
;
1205 if( !(newstr
= csv_remove_quotes(s
)) )
1209 if (item
[i
] != NULL
) {
1210 char *oldstr
= item
[i
];
1212 item
[i
] = strconcat(newstr
, CSV_DUPLICATE_SEPARATOR
,
1225 csv_is_valid_quote_end(char *p
)
1233 else if(!ISSPACE(*p
))
1241 csv_is_valid_quote_start(char *p
)
1246 else if(!ISSPACE(*p
))
1254 csv_parse_line(char *line
, int *table_base
, size_t table_size
)
1258 bool in_quote
= FALSE
;
1261 item
= item_create();
1263 for(p
= start
= line
, field
= 0; *p
; p
++) {
1265 if(csv_is_valid_quote_end(p
))
1268 if ( (((p
- start
) / sizeof (char)) < 2 ) &&
1269 csv_is_valid_quote_start(p
) )
1273 if(*p
== ',' && !in_quote
) {
1275 csv_store_item(item
,
1276 csv_field_to_item(table_base
,table_size
,field
),
1285 csv_store_item(item
, csv_field_to_item(table_base
, table_size
, field
),
1288 csv_convert_emails(item_fget(item
, EMAIL
));
1289 add_item2database(item
);
1294 csv_parse_file_common(FILE *in
, int *conv_table
, size_t table_size
)
1299 line
= getaline(in
);
1301 if(line
&& *line
&& *line
!= CSV_COMMENT_CHAR
)
1302 csv_parse_line(line
, conv_table
, table_size
);
1311 csv_parse_file(FILE *in
)
1313 return csv_parse_file_common(in
, csv_conv_table
,
1314 CSV_TABLE_SIZE(csv_conv_table
));
1318 allcsv_parse_file(FILE *in
)
1320 return csv_parse_file_common(in
, allcsv_conv_table
,
1321 CSV_TABLE_SIZE(allcsv_conv_table
));
1325 palmcsv_parse_file(FILE *in
)
1327 return csv_parse_file_common(in
, palmcsv_conv_table
,
1328 CSV_TABLE_SIZE(palmcsv_conv_table
));
1332 * end of csv import filter
1336 * vCard import filter
1339 static char *vcard_fields
[] = {
1341 "EMAIL", /* EMAIL */
1342 "ADR", /* ADDRESS */
1343 "ADR", /* ADDRESS2 - not used */
1347 "ADR", /* COUNTRY */
1349 "TEL", /* WORKPHONE */
1351 "TEL", /* MOBILEPHONE */
1352 "NICKNAME", /* NICK */
1355 NULL
/* not implemented: ANNIVERSARY, ITEM_FIELDS */
1359 * mappings between vCard ADR field and abook's ADDRESS
1360 * see rfc2426 section 3.2.1
1362 static int vcard_address_fields
[] = {
1363 -1, /* vCard(post office box) - not used */
1364 -1, /* vCard(the extended address) - not used */
1365 2, /* vCard(the street address) - ADDRESS */
1366 4, /* vCard(the locality) - CITY */
1367 5, /* vCard(the region) - STATE */
1368 6, /* vCard(the postal code) - ZIP */
1369 7 /* vCard(the country name) - COUNTRY */
1374 VCARD_KEY_ATTRIBUTE
,
1379 vcard_get_line_element(char *line
, int element
)
1382 char *line_copy
= 0;
1388 line_copy
= xstrdup(line
);
1390 /* make newline characters if exist end of string */
1391 for(i
=0; line_copy
[i
]; i
++) {
1392 if(line_copy
[i
] == '\r' || line_copy
[i
] == '\n') {
1393 line_copy
[i
] = '\0';
1398 /* separate key from value */
1399 for(i
=0; line_copy
[i
]; i
++) {
1400 if(line_copy
[i
] == ':') {
1401 line_copy
[i
] = '\0';
1403 value
= &line_copy
[i
+1];
1408 /* separate key from key attributes */
1410 for(i
=0; key
[i
]; i
++) {
1413 key_attr
= &key
[i
+1];
1422 result
= xstrdup(key
);
1424 case VCARD_KEY_ATTRIBUTE
:
1426 result
= xstrdup(key_attr
);
1430 result
= xstrdup(value
);
1439 vcard_parse_email(list_item item
, char *line
)
1443 email
= vcard_get_line_element(line
, VCARD_VALUE
);
1446 item
[1] = strconcat(item
[1], ",", email
, 0);
1455 vcard_parse_address(list_item item
, char *line
)
1460 char *address_field
;
1462 value
= vcard_get_line_element(line
, VCARD_VALUE
);
1466 address_field
= value
;
1467 for(i
=k
=0; value
[i
]; i
++) {
1468 if(value
[i
] == ';') {
1470 if(vcard_address_fields
[k
] >= 0) {
1471 item
[vcard_address_fields
[k
]] = xstrdup(address_field
);
1473 address_field
= &value
[i
+1];
1475 if((k
+1)==(sizeof(vcard_address_fields
)/sizeof(*vcard_address_fields
)))
1479 item
[vcard_address_fields
[k
]] = xstrdup(address_field
);
1484 vcard_parse_phone(list_item item
, char *line
)
1487 char *type
= vcard_get_line_element(line
, VCARD_KEY_ATTRIBUTE
);
1488 char *value
= vcard_get_line_element(line
, VCARD_VALUE
);
1490 /* set the standard number */
1492 item
[index
] = value
;
1496 * see rfc2426 section 3.3.1
1498 else if (strstr(type
, "TYPE=") == type
){
1499 if (strcasestr(type
, "home")) {
1500 item
[index
] = xstrdup(value
);
1502 if (strcasestr(type
, "work")) {
1503 item
[index
+1] = xstrdup(value
);
1505 if (strcasestr(type
, "fax")) {
1506 item
[index
+2] = xstrdup(value
);
1508 if (strcasestr(type
, "cell")) {
1509 item
[index
+3] = xstrdup(value
);
1518 vcard_parse_line(list_item item
, char *line
)
1523 for(i
=0; vcard_fields
[i
]; i
++) {
1524 key
= vcard_fields
[i
];
1526 if(!strncmp(key
, line
, strlen(key
))) {
1528 vcard_parse_email(item
, line
);
1531 vcard_parse_address(item
, line
);
1534 vcard_parse_phone(item
, line
);
1537 item
[i
] = vcard_get_line_element(line
, VCARD_VALUE
);
1545 vcard_parse_item(FILE *in
)
1548 list_item item
= item_create();
1551 line
= getaline(in
);
1553 if(line
&& !strncmp("END:VCARD", line
, 9)) {
1558 vcard_parse_line(item
, line
);
1563 add_item2database(item
);
1568 vcard_parse_file(FILE *in
)
1573 line
= getaline(in
);
1575 if(line
&& !strncmp("BEGIN:VCARD", line
, 11)) {
1577 vcard_parse_item(in
);
1588 * end of vCard import filter
1592 * csv addressbook export filters
1595 #define CSV_LAST (-1)
1596 #define CSV_UNDEFINED (-2)
1597 #define CSV_SPECIAL(X) (-3 - (X))
1598 #define CSV_IS_SPECIAL(X) ((X) <= -3)
1601 csv_export_common(FILE *out
, struct db_enumerator e
,
1602 int fields
[], void (*special_func
)(FILE *, int, int))
1606 db_enumerate_items(e
) {
1607 for(i
= 0; fields
[i
] != CSV_LAST
; i
++) {
1608 if(fields
[i
] == CSV_UNDEFINED
)
1609 fprintf(out
, "\"\"");
1610 else if(CSV_IS_SPECIAL(fields
[i
])) {
1612 (*special_func
)(out
, e
.item
, fields
[i
]);
1615 strchr(safe_str(database[e.item][field_idx(fields[i])]), ',') ||
1616 strchr(safe_str(database[e.item][field_idx(fields[i])]), '\"')) ?
1618 safe_str(database[e.item][field_idx(fields[i])])
1620 fprintf(out
, "\"%s\"",
1621 safe_str(db_fget(e
.item
,fields
[i
])));
1623 if(fields
[i
+ 1] != CSV_LAST
)
1633 csv_export_database(FILE *out
, struct db_enumerator e
)
1635 int csv_export_fields
[] = {
1644 csv_export_common(out
, e
, csv_export_fields
, NULL
);
1650 allcsv_export_database(FILE *out
, struct db_enumerator e
)
1653 * TODO: Should get these atomatically from abook_fileds
1656 int allcsv_export_fields
[] = {
1677 fprintf(out
, "\"NAME\",");
1678 fprintf(out
, "\"EMAIL\",");
1679 fprintf(out
, "\"ADDRESS\",");
1680 fprintf(out
, "\"ADDRESS2\",");
1681 fprintf(out
, "\"CITY\",");
1682 fprintf(out
, "\"STATE\",");
1683 fprintf(out
, "\"ZIP\",");
1684 fprintf(out
, "\"COUNTRY\",");
1685 fprintf(out
, "\"PHONE\",");
1686 fprintf(out
, "\"WORKPHONE\",");
1687 fprintf(out
, "\"FAX\",");
1688 fprintf(out
, "\"MOBILEPHONE\",");
1689 fprintf(out
, "\"NICK\",");
1690 fprintf(out
, "\"URL\",");
1691 fprintf(out
, "\"NOTES\",");
1692 fprintf(out
, "\"ANNIVERSARY\"\n");
1694 csv_export_common(out
, e
, allcsv_export_fields
, NULL
);
1703 #define PALM_CSV_NAME CSV_SPECIAL(0)
1704 #define PALM_CSV_END CSV_SPECIAL(1)
1705 #define PALM_CSV_CAT CSV_SPECIAL(2)
1708 palm_split_and_write_name(FILE *out
, char *name
)
1714 if ( (p
= strchr(name
, ' ')) ) {
1718 fprintf(out
, "\"%s\",\"" , p
+ 1);
1719 fwrite((void *)name
, p
- name
, sizeof(char), out
);
1722 fprintf(out
, "\"%s\"", safe_str(name
));
1727 palm_csv_handle_specials(FILE *out
, int item
, int field
)
1731 palm_split_and_write_name(out
, db_name_get(item
));
1734 fprintf(out
, "\"abook\"");
1737 fprintf(out
, "\"0\"");
1745 palm_export_database(FILE *out
, struct db_enumerator e
)
1747 int palm_export_fields
[] = {
1748 PALM_CSV_NAME
, /* LASTNAME, FIRSTNAME */
1749 CSV_UNDEFINED
, /* TITLE */
1750 CSV_UNDEFINED
, /* COMPANY */
1751 WORKPHONE
, /* WORK PHONE */
1752 PHONE
, /* HOME PHONE */
1754 MOBILEPHONE
, /* OTHER */
1756 ADDRESS
, /* ADDRESS */
1760 COUNTRY
, /* COUNTRY */
1761 NICK
, /* DEFINED 1 */
1762 URL
, /* DEFINED 2 */
1763 CSV_UNDEFINED
, /* DEFINED 3 */
1764 CSV_UNDEFINED
, /* DEFINED 4 */
1766 PALM_CSV_END
, /* "0" */
1767 PALM_CSV_CAT
, /* CATEGORY */
1771 csv_export_common(out
, e
, palm_export_fields
, palm_csv_handle_specials
);
1777 * end of csv export filters
1781 * GnomeCard (VCard) addressbook export filter
1785 gcrd_export_database(FILE *out
, struct db_enumerator e
)
1789 abook_list
*emails
, *em
;
1791 db_enumerate_items(e
) {
1792 fprintf(out
, "BEGIN:VCARD\r\nFN:%s\r\n",
1793 safe_str(db_name_get(e
.item
)));
1795 name
= get_surname(db_name_get(e
.item
));
1796 for( j
= strlen(db_name_get(e
.item
)) - 1; j
>= 0; j
-- ) {
1797 if((db_name_get(e
.item
))[j
] == ' ')
1800 fprintf(out
, "N:%s;%.*s\r\n",
1803 safe_str(db_name_get(e
.item
))
1808 if(db_fget(e
.item
, ADDRESS
))
1809 fprintf(out
, "ADR:;;%s;%s;%s;%s;%s;%s\r\n",
1810 safe_str(db_fget(e
.item
, ADDRESS
)),
1811 safe_str(db_fget(e
.item
, ADDRESS2
)),
1812 safe_str(db_fget(e
.item
, CITY
)),
1813 safe_str(db_fget(e
.item
, STATE
)),
1814 safe_str(db_fget(e
.item
, ZIP
)),
1815 safe_str(db_fget(e
.item
, COUNTRY
))
1818 if(db_fget(e
.item
, PHONE
))
1819 fprintf(out
, "TEL;HOME:%s\r\n",
1820 db_fget(e
.item
, PHONE
));
1821 if(db_fget(e
.item
, WORKPHONE
))
1822 fprintf(out
, "TEL;WORK:%s\r\n",
1823 db_fget(e
.item
, WORKPHONE
));
1824 if(db_fget(e
.item
, FAX
))
1825 fprintf(out
, "TEL;FAX:%s\r\n",
1826 db_fget(e
.item
, FAX
));
1827 if(db_fget(e
.item
, MOBILEPHONE
))
1828 fprintf(out
, "TEL;CELL:%s\r\n",
1829 db_fget(e
.item
, MOBILEPHONE
));
1831 tmp
= db_email_get(e
.item
);
1833 emails
= csv_to_abook_list(tmp
);
1835 for(em
= emails
; em
; em
= em
->next
)
1836 fprintf(out
, "EMAIL;INTERNET:%s\r\n", em
->data
);
1838 abook_list_free(&emails
);
1842 if(db_fget(e
.item
, NOTES
))
1843 fprintf(out
, "NOTE:%s\r\n",
1844 db_fget(e
.item
, NOTES
));
1845 if(db_fget(e
.item
, URL
))
1846 fprintf(out
, "URL:%s\r\n",
1847 db_fget(e
.item
, URL
));
1849 fprintf(out
, "END:VCARD\r\n\r\n");
1857 * end of GnomeCard export filter
1862 * mutt alias export filter
1866 mutt_alias_genalias(int i
)
1870 if(db_fget(i
, NICK
))
1871 return xstrdup(db_fget(i
, NICK
));
1873 tmp
= xstrdup(db_name_get(i
));
1875 if( ( pos
= strchr(tmp
, ' ') ) )
1884 mutt_alias_export(FILE *out
, struct db_enumerator e
)
1886 char email
[MAX_EMAIL_LEN
];
1889 db_enumerate_items(e
) {
1890 alias
= mutt_alias_genalias(e
.item
);
1891 get_first_email(email
, e
.item
);
1892 fprintf(out
, *email
? "alias %s %s <%s>\n": "alias %s %s%s\n",
1894 db_name_get(e
.item
),
1903 * end of mutt alias export filter
1908 * printable export filter
1913 text_write_address_us(FILE *out
, int i
) {
1914 fprintf(out
, "\n%s", db_fget(i
, ADDRESS
));
1916 if(db_fget(i
, ADDRESS2
))
1917 fprintf(out
, "\n%s", db_fget(i
, ADDRESS2
));
1919 if(db_fget(i
, CITY
))
1920 fprintf(out
, "\n%s", db_fget(i
, CITY
));
1922 if(db_fget(i
, STATE
) || db_fget(i
, ZIP
)) {
1925 if(db_fget(i
, STATE
)) {
1926 fprintf(out
, "%s", db_fget(i
, STATE
));
1932 fprintf(out
, "%s", db_fget(i
, ZIP
));
1935 if(db_fget(i
, COUNTRY
))
1936 fprintf(out
, "\n%s", db_fget(i
, COUNTRY
));
1941 text_write_address_uk(FILE *out
, int i
) {
1944 for(j
= ADDRESS
; j
<= COUNTRY
; j
++)
1946 fprintf(out
, "\n%s", db_fget(i
, j
));
1950 text_write_address_eu(FILE *out
, int i
) {
1951 fprintf(out
, "\n%s", db_fget(i
, ADDRESS
));
1953 if(db_fget(i
, ADDRESS2
))
1954 fprintf(out
, "\n%s", db_fget(i
, ADDRESS2
));
1956 if(db_fget(i
, ZIP
) || db_fget(i
, CITY
)) {
1959 if(db_fget(i
, ZIP
)) {
1960 fprintf(out
, "%s", db_fget(i
, ZIP
));
1961 if(db_fget(i
, CITY
))
1965 fprintf(out
, "%s", safe_str(db_fget(i
, CITY
)));
1968 if(db_fget(i
, STATE
))
1969 fprintf(out
, "\n%s", db_fget(i
, STATE
));
1971 if(db_fget(i
, COUNTRY
))
1972 fprintf(out
, "\n%s", db_fget(i
, COUNTRY
));
1976 text_export_database(FILE * out
, struct db_enumerator e
)
1978 abook_list
*emails
, *em
;
1980 char *realname
= get_real_name(), *str
= NULL
, *tmp
;
1981 char *style
= opt_get_str(STR_ADDRESS_STYLE
);
1984 "-----------------------------------------\n%s's address book\n"
1985 "-----------------------------------------\n\n\n",
1989 db_enumerate_items(e
) {
1991 "-----------------------------------------\n\n");
1992 fprintf(out
, "%s", db_name_get(e
.item
));
1993 if(db_fget(e
.item
, NICK
) && *db_fget(e
.item
, NICK
))
1994 fprintf(out
, "\n(%s)", db_fget(e
.item
, NICK
));
1997 tmp
= db_email_get(e
.item
);
1999 emails
= csv_to_abook_list(tmp
);
2002 for(em
= emails
; em
; em
= em
->next
)
2003 fprintf(out
, "%s\n", em
->data
);
2005 abook_list_free(&emails
);
2009 if(db_fget(e
.item
, ADDRESS
)) {
2010 if(!safe_strcmp(style
, "us")) /* US like */
2011 text_write_address_us(out
, e
.item
);
2012 else if(!safe_strcmp(style
, "uk")) /* UK like */
2013 text_write_address_uk(out
, e
.item
);
2015 text_write_address_eu(out
, e
.item
);
2020 if((db_fget(e
.item
, PHONE
)) ||
2021 (db_fget(e
.item
, WORKPHONE
)) ||
2022 (db_fget(e
.item
, FAX
)) ||
2023 (db_fget(e
.item
, MOBILEPHONE
))) {
2025 for(j
= PHONE
; j
<= MOBILEPHONE
; j
++)
2026 if(db_fget(e
.item
, j
)) {
2027 get_field_info(field_id(j
),
2029 fprintf(out
, "%s: %s\n", str
,
2030 db_fget(e
.item
, j
));
2034 if(db_fget(e
.item
, URL
))
2035 fprintf(out
, "\n%s\n", db_fget(e
.item
, URL
));
2036 if(db_fget(e
.item
, NOTES
))
2037 fprintf(out
, "\n%s\n", db_fget(e
.item
, NOTES
));
2042 fprintf(out
, "-----------------------------------------\n");
2048 * end of printable export filter
2052 * elm alias export filter
2056 elm_alias_export(FILE *out
, struct db_enumerator e
)
2058 char email
[MAX_EMAIL_LEN
];
2061 db_enumerate_items(e
) {
2062 alias
= mutt_alias_genalias(e
.item
);
2063 get_first_email(email
, e
.item
);
2064 fprintf(out
, "%s = %s = %s\n",alias
,db_name_get(e
.item
),email
);
2072 * end of elm alias export filter
2077 * Spruce export filter
2081 spruce_export_database (FILE *out
, struct db_enumerator e
)
2083 char email
[MAX_EMAIL_LEN
];
2085 fprintf(out
, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
2087 db_enumerate_items(e
) {
2088 get_first_email(email
, e
.item
);
2089 if(strcmp(email
, "")) {
2090 fprintf(out
, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
2092 db_name_get(e
.item
),
2094 safe_str(db_fget(e
.item
, NOTES
))
2099 fprintf (out
, "# End of address book file.\n");
2105 * end of Spruce export filter
2109 * wanderlust addressbook export filter
2113 wl_export_database(FILE *out
, struct db_enumerator e
)
2115 char email
[MAX_EMAIL_LEN
];
2117 fprintf(out
, "# Wanderlust address book written by %s\n\n", PACKAGE
);
2118 db_enumerate_items(e
) {
2119 get_first_email(email
, e
.item
);
2122 "%s\t\"%s\"\t\"%s\"\n",
2124 safe_str(db_fget(e
.item
, NICK
)),
2125 safe_str(db_name_get(e
.item
))
2130 fprintf (out
, "\n# End of address book file.\n");
2136 * end of wanderlust addressbook export filter
2140 * BSD calendar export filter
2144 bsdcal_export_database(FILE *out
, struct db_enumerator e
)
2146 db_enumerate_items(e
) {
2147 int year
, month
= 0, day
= 0;
2148 char *anniversary
= db_fget(e
.item
, ANNIVERSARY
);
2151 parse_date_string(anniversary
, &day
, &month
, &year
);
2154 _("%02d/%02d\tAnniversary of %s\n"),
2157 safe_str(db_name_get(e
.item
))
2166 * end of BSD calendar export filter