5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
16 #include <sys/types.h>
17 #include "abook_curses.h"
28 extern list_item *database;
29 extern struct abook_field abook_fields[];
32 * function declarations
36 * import filter prototypes
39 static int ldif_parse_file(FILE *handle);
40 static int mutt_parse_file(FILE *in);
41 static int pine_parse_file(FILE *in);
42 static int csv_parse_file(FILE *in);
45 * export filter prototypes
48 static int ldif_export_database(FILE *out, struct db_enumerator e);
49 static int html_export_database(FILE *out, struct db_enumerator e);
50 static int pine_export_database(FILE *out, struct db_enumerator e);
51 static int csv_export_database(FILE *out, struct db_enumerator e);
52 static int gcrd_export_database(FILE *out, struct db_enumerator e);
53 static int mutt_alias_export(FILE *out, struct db_enumerator e);
54 static int elm_alias_export(FILE *out, struct db_enumerator e);
55 static int text_export_database(FILE *out, struct db_enumerator e);
56 static int spruce_export_database(FILE *out, struct db_enumerator e);
59 * end of function declarations
62 struct abook_input_filter i_filters[] = {
63 { "abook", "abook native format", parse_database },
64 { "ldif", "ldif / Netscape addressbook", ldif_parse_file },
65 { "mutt", "mutt alias", mutt_parse_file },
66 { "pine", "pine addressbook", pine_parse_file },
67 { "csv", "comma separated values", csv_parse_file },
71 struct abook_output_filter e_filters[] = {
72 { "abook", "abook native format", write_database },
73 { "ldif", "ldif / Netscape addressbook (.4ld)", ldif_export_database },
74 { "mutt", "mutt alias", mutt_alias_export },
75 { "html", "html document", html_export_database },
76 { "pine", "pine addressbook", pine_export_database },
77 { "gcrd", "GnomeCard (VCard) addressbook", gcrd_export_database },
78 { "csv", "comma separated values", csv_export_database },
79 { "elm", "elm alias", elm_alias_export },
80 { "text", "plain text", text_export_database },
81 { "spruce", "Spruce address book", spruce_export_database },
95 for(i=0; *i_filters[i].filtname ; i++)
96 printf("\t%s\t%s\n", i_filters[i].filtname,
102 for(i=0; *e_filters[i].filtname ; i++)
103 printf("\t%s\t%s\n", e_filters[i].filtname,
110 number_of_output_filters()
114 for(i=0; *e_filters[i].filtname ; i++)
121 number_of_input_filters()
125 for(i=0; *i_filters[i].filtname ; i++)
134 char *username = getenv("USER");
135 struct passwd *pwent;
139 pwent = getpwnam(username);
141 if( (tmp = (char *)malloc(strlen(pwent->pw_gecos) +1)) == NULL)
142 return strdup(username);
144 rtn = sscanf(pwent->pw_gecos, "%[^,]", tmp);
145 if (rtn == EOF || rtn == 0) {
147 return strdup(username);
156 static int i_read_file(char *filename, int (*func) (FILE *in));
165 refresh_statusline();
166 headerline("import database");
168 mvaddstr(3, 1, "please select a filter");
171 for(i=0; *i_filters[i].filtname ; i++)
172 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
173 i_filters[i].filtname,
176 mvprintw(6 + i, 6, "x -\tcancel");
188 filter = getch() - 'a';
189 if(filter == 'x' - 'a' ||
190 filter >= number_of_input_filters() || filter < 0) {
195 mvaddstr(5+filter, 2, "->");
197 filename = ask_filename("Filename: ");
203 if( i_read_file(filename, i_filters[filter].func ) )
204 statusline_msg("Error occured while opening the file");
205 else if( tmp == items )
206 statusline_msg("Hmm.., file seems not to be a valid file");
217 i_read_file(char *filename, int (*func) (FILE *in))
222 if( ( in = abook_fopen( filename, "r" ) ) == NULL )
233 import_file(char filtname[FILTNAME_LEN], char *filename)
240 if( ! strncasecmp(i_filters[i].filtname, filtname,
243 if( ! *i_filters[i].filtname ) {
252 if( !strcmp(filename, "-") ) {
254 if( (fstat(fileno(stdin), &s)) == -1 || S_ISDIR(s.st_mode))
257 ret = (*i_filters[i].func) (stdin);
259 ret = i_read_file(filename, i_filters[i].func);
271 static int e_write_file(char *filename,
272 int (*func) (FILE *in, struct db_enumerator e), int mode);
282 refresh_statusline();
283 headerline("export database");
285 mvaddstr(3, 1, "please select a filter");
288 for(i=0; *e_filters[i].filtname ; i++)
289 mvprintw(5 + i, 6, "%c -\t%s\t%s\n", 'a' + i,
290 e_filters[i].filtname,
293 mvprintw(6 + i, 6, "x -\tcancel");
300 int enum_mode = ENUM_ALL;
305 filter = getch() - 'a';
306 if(filter == 'x' - 'a' ||
307 filter >= number_of_output_filters() || filter < 0) {
312 mvaddstr(5+filter, 2, "->");
314 if( selected_items() ) {
315 statusline_addstr("Export All/Selected/Cancel (A/s/c)");
316 switch( tolower(getch()) ) {
318 enum_mode = ENUM_SELECTED;
327 filename = ask_filename("Filename: ");
333 if( e_write_file(filename, e_filters[filter].func, enum_mode ) )
334 statusline_msg("Error occured while exporting");
343 e_write_file(char *filename, int (*func) (FILE *in, struct db_enumerator e),
348 struct db_enumerator enumerator = init_db_enumerator(mode);
350 if( (out = fopen(filename, "a")) == NULL )
356 ret = (*func) (out, enumerator);
364 fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode)
367 struct db_enumerator e = init_db_enumerator(enum_mode);
370 if( ! strncasecmp(e_filters[i].filtname, filtname,
373 if( ! *e_filters[i].filtname ) {
379 return (e_filters[i].func) (handle, e);
385 export_file(char filtname[FILTNAME_LEN], char *filename)
387 const int mode = ENUM_ALL;
390 struct db_enumerator e = init_db_enumerator(mode);
393 if( ! strncasecmp(e_filters[i].filtname, filtname,
396 if( ! *e_filters[i].filtname ) {
405 if( !strcmp(filename, "-") )
406 ret = (e_filters[i].func) (stdout, e);
408 ret = e_write_file(filename, e_filters[i].func, mode);
414 * end of common functions
423 static void ldif_fix_string(char *str);
425 #define LDIF_ITEM_FIELDS 16
427 typedef char* ldif_item[LDIF_ITEM_FIELDS];
429 static ldif_item ldif_field_names = {
441 "facsimiletelephonenumber",
445 "objectclass", /* this must be the last entry */
448 static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
451 ADDRESS, /* "streetaddress" */
452 ADDRESS2, /* "streetaddress2" */
453 CITY, /* "locality" */
455 ZIP, /* "postalcode" */
456 COUNTRY, /* "countryname" */
457 PHONE, /* "homephone" */
458 NOTES, /* "description" */
460 FAX, /* "facsimiletelephonenumber" */
461 MOBILEPHONE, /* "cellphone" */
462 WORKPHONE, /* "xmozillaanyphone" */
463 NICK, /* "xmozillanickname" */
464 -1, /* "objectclass" */ /* this must be the last entry */
469 ldif_read_line(FILE *in)
482 if( feof(in) || !line )
491 fseek(in, pos, SEEK_SET);
501 buf = strconcat(buf, ptr, NULL);
506 if(buf && *buf == '#' ) {
515 ldif_add_item(ldif_item ldif_item)
517 list_item abook_item;
520 memset(abook_item, 0, sizeof(abook_item));
522 if( !ldif_item[LDIF_ITEM_FIELDS -1] )
526 for(i=0; i < LDIF_ITEM_FIELDS; i++) {
527 if(ldif_conv_table[i] >= 0 && ldif_item[i] && *ldif_item[i] )
528 abook_item[ldif_conv_table[i]] = strdup(ldif_item[i]);
531 add_item2database(abook_item);
534 for(i=0; i < LDIF_ITEM_FIELDS; i++)
535 my_free(ldif_item[i]);
540 ldif_convert(ldif_item item, char *type, char *value)
544 if( !strcmp(type, "dn") ) {
549 for(i=0; i < LDIF_ITEM_FIELDS; i++) {
550 if( !safe_strcmp(ldif_field_names[i], type) && *value ) {
551 if( i == LDIF_ITEM_FIELDS -1) /* this is a dirty hack */
552 if( safe_strcmp("person", value))
556 item[i] = strdup(value);
562 ldif_parse_file(FILE *handle)
569 memset(item, 0, sizeof(item));
572 if( ! (line = ldif_read_line(handle)) )
575 if( -1 == ( str_parse_line(line, &type, &value, &vlen)) ) {
577 continue; /* just skip the errors */
580 ldif_fix_string(value);
582 ldif_convert(item, type, value);
585 } while ( !feof(handle) );
587 ldif_convert(item, "dn", "");
593 ldif_fix_string(char *str)
597 for( i = 0, j = 0; j < (int)strlen(str); i++, j++)
598 str[i] = ( str[j] == (char)0xc3 ?
599 (char) str[++j] + (char) 0x40 :
610 * mutt alias import filter
616 mutt_read_line(FILE *in, char **alias, char **rest)
618 char *line, *ptr, *tmp;
620 if( !(line = ptr = getaline(in)) )
621 return 1; /* error / EOF */
623 while( ISSPACE(*ptr) )
626 if( strncmp("alias", ptr, 5) ) {
633 while( ISSPACE(*ptr) )
638 while( ! ISSPACE(*ptr) )
641 if( (*alias = (char *)malloc(ptr-tmp+1)) == NULL) {
646 strncpy(*alias, tmp, ptr-tmp);
647 *(*alias + (ptr - tmp)) = 0;
649 while( ISSPACE(*ptr) )
659 mutt_parse_email(list_item item)
661 char *line = item[NAME];
662 char *start = line, *tmp;
666 tmp = strconcat("From: ", line, NULL);
667 getname(tmp, &name, &email);
679 while( (start = strchr(start, ',')) && i++ < MAX_EMAILS - 1) {
680 tmp = strconcat("From: ", ++start, NULL);
681 getname(tmp, &name, &email);
686 tmp = strconcat(item[EMAIL], ",", email, NULL);
697 mutt_parse_file(FILE *in)
702 memset(item, 0, sizeof(item));
704 if( !mutt_read_line(in, &item[NICK],
706 mutt_parse_email(item);
709 free_list_item(item);
713 add_item2database(item);
720 * end of mutt alias import filter
729 ldif_fput_type_and_value(FILE *out,char *type, char *value )
733 tmp = ldif_type_and_value(type, value, strlen(value));
741 ldif_export_database(FILE *out, struct db_enumerator e)
743 char email[MAX_EMAILSTR_LEN];
745 fprintf(out, "version: 1\n");
747 db_enumerate_items(e) {
750 get_first_email(email, e.item);
752 tmp = mkstr("cn=%s,mail=%s", database[e.item][NAME], email);
753 ldif_fput_type_and_value(out, "dn", tmp);
756 for(j=0; j < LDIF_ITEM_FIELDS; j++) {
757 if(ldif_conv_table[j] >= 0) {
758 if(ldif_conv_table[j] == EMAIL)
759 ldif_fput_type_and_value(out,
760 ldif_field_names[j], email);
761 else if(database[e.item][ldif_conv_table[j]])
762 ldif_fput_type_and_value(out,
764 database[e.item][ldif_conv_table[j]]);
768 fprintf(out, "objectclass: top\n"
769 "objectclass: person\n\n");
776 * end of ldif export filter
783 static void html_export_write_head(FILE *out, int extra_column);
784 static void html_export_write_tail(FILE *out);
787 html_export_database(FILE *out, struct db_enumerator e)
789 char tmp[MAX_EMAILSTR_LEN];
790 int extra_column = options_get_int("extra_column");
795 extra_column = (extra_column > 2 && extra_column < ITEM_FIELDS) ?
796 extra_column : PHONE;
798 html_export_write_head(out, extra_column);
800 db_enumerate_items(e) {
801 get_first_email(tmp, e.item);
803 fprintf(out, "<tr>\n<td><a href=\"mailto:%s\">%s</a>\n",
805 database[e.item][NAME] );
807 fprintf(out, "<tr>\n<td>%s\n",
808 database[e.item][NAME] );
810 fprintf(out, "<td>%s\n<td>%s\n",
811 database[e.item][EMAIL],
812 safe_str(database[e.item][extra_column]) );
813 fprintf(out, "</tr>\n\n");
816 html_export_write_tail(out);
823 html_export_write_head(FILE *out, int extra_column)
825 char *realname = get_real_name();
827 fprintf(out, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n");
828 fprintf(out, "<html>\n<head>\n <title>%s's addressbook</title>", realname );
829 fprintf(out, "\n</head>\n<body>\n");
830 fprintf(out, "\n<h2>%s's addressbook</h2>\n", realname );
831 fprintf(out, "<br><br>\n\n");
833 fprintf(out, "<table border=\"1\" align=\"center\">\n");
834 fprintf(out, "\n<tr><th>Name<th>E-mail address(es)<th>%s</tr>\n\n",
835 abook_fields[extra_column].name);
841 html_export_write_tail(FILE *out)
843 fprintf(out, "\n</table>\n");
844 fprintf(out, "\n</body>\n</html>\n");
848 * end of html export filter
853 * pine addressbook import filter
857 pine_fixbuf(char *buf)
861 for(i=0,j=0; j < (int)strlen(buf); i++, j++)
862 buf[i] = buf[j] == '\n' ? buf[++j] : buf[j];
866 pine_convert_emails(char *s)
871 if( s == NULL || *s != '(' )
877 if( ( tmp = strchr(s,')')) )
880 for(i=1; ( tmp = strchr(s, ',') ) != NULL ; i++, s=tmp+1 )
881 if( i > MAX_EMAILS - 1 ) {
889 pine_parse_buf(char *buf)
896 int pine_conv_table[]= {NICK, NAME, EMAIL, -1, NOTES};
898 memset(&item, 0, sizeof(item) );
900 for(i=0, last=0; !last ; i++) {
901 if( ! (end = strchr(start, '\t')) )
904 len = last ? strlen(start) : (int) (end-start);
905 len = min(len, 400-1);
907 if(i < (int)(sizeof(pine_conv_table) / sizeof(*pine_conv_table))
908 && pine_conv_table[i] >= 0) {
909 strncpy(tmp, start, len);
911 item[pine_conv_table[i]] = strdup(tmp);
916 pine_convert_emails(item[EMAIL]);
917 add_item2database(item);
921 #define LINESIZE 1024
924 pine_parse_file(FILE *in)
931 fgets(line, LINESIZE, in);
935 buf = (char *) realloc(buf, i*LINESIZE);
938 fgets(line, LINESIZE, in);
940 if(*ptr != ' ' || feof(in) )
963 * end of pine addressbook import filter
968 * pine addressbook export filter
970 * filter doesn't wrap the lines as it should but Pine seems to handle
971 * created files without problems - JH
975 pine_export_database(FILE *out, struct db_enumerator e)
977 db_enumerate_items(e) {
978 fprintf(out, have_multiple_emails(e.item) ?
979 "%s\t%s\t(%s)\t\t%s\n" : "%s\t%s\t%s\t\t%s\n",
980 safe_str(database[e.item][NICK]),
981 safe_str(database[e.item][NAME]),
982 safe_str(database[e.item][EMAIL]),
983 safe_str(database[e.item][NOTES])
991 * end of pine addressbook export filter
1000 * these files should be parsed according to a certain
1001 * lay out, or the default if layout is not given, at
1002 * the moment only default is done...
1005 #define CSV_COMMENT_CHAR '#'
1007 static int csv_conv_table[] = {
1016 csv_convert_emails(char *s)
1024 for(i=1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1 )
1025 if( i > MAX_EMAILS - 1 ) {
1033 csv_remove_quotes(char *s)
1035 char *copy, *trimmed;
1038 copy = trimmed = strdup(s);
1041 len = strlen(trimmed);
1042 if(trimmed[len - 1] == '\"' && *trimmed == '\"') {
1047 trimmed[len - 1] = 0;
1049 trimmed = strdup(trimmed);
1059 csv_store_field(list_item item, char *s, int field)
1061 char *newstr = NULL;
1066 if( !(newstr = csv_remove_quotes(s)) )
1069 if(field < (int)(sizeof(csv_conv_table) / sizeof(*csv_conv_table))
1070 && csv_conv_table[field] >= 0) {
1071 item[csv_conv_table[field]] = newstr;
1078 csv_is_valid_quote_end(char *p)
1086 else if(!ISSPACE(*p))
1094 csv_is_valid_quote_start(char *p)
1099 else if(!ISSPACE(*p))
1107 csv_parse_line(char *line)
1111 bool in_quote = FALSE;
1114 memset(item, 0, sizeof(item));
1116 for(p = start = line, field = 0; *p; p++) {
1118 if(csv_is_valid_quote_end(p))
1121 if ( (((p - start) / sizeof (char)) < 2 ) &&
1122 csv_is_valid_quote_start(p) )
1126 if( *p == ',' && !in_quote) {
1128 csv_store_field(item, start, field);
1136 csv_store_field(item, start, field);
1138 csv_convert_emails(item[EMAIL]);
1139 add_item2database(item);
1144 csv_parse_file(FILE *in)
1149 line = getaline(in);
1151 if(line && *line && *line != CSV_COMMENT_CHAR)
1152 csv_parse_line(line);
1161 * end of csv import filter
1165 * csv addressbook export filter
1169 csv_export_database(FILE *out, struct db_enumerator e)
1172 int csv_export_fields[] = {
1181 db_enumerate_items(e) {
1182 for(j = 0; csv_export_fields[j] >= 0; j++) {
1184 strchr(safe_str(database[e.item][csv_export_fields[j]]), ',') ||
1185 strchr(safe_str(database[e.item][csv_export_fields[j]]), '\"')
1188 safe_str(database[e.item][csv_export_fields[j]])
1190 if(csv_export_fields[j+1] >= 0)
1202 * end of csv export filter
1207 * GnomeCard (VCard) addressbook export filter
1211 gcrd_export_database(FILE *out, struct db_enumerator e)
1213 char emails[MAX_EMAILS][MAX_EMAIL_LEN];
1217 db_enumerate_items(e) {
1218 fprintf(out, "BEGIN:VCARD\nFN:%s\n",
1219 safe_str(database[e.item][NAME]));
1221 name = get_surname(database[e.item][NAME]);
1222 for( j = strlen(database[e.item][NAME]) - 1; j >= 0; j-- ) {
1223 if(database[e.item][NAME][j] == ' ')
1226 fprintf(out, "N:%s;%.*s\n",
1229 safe_str(database[e.item][NAME])
1234 if ( database[e.item][ADDRESS] )
1235 fprintf(out, "ADR:;;%s;%s;%s;%s;%s;%s\n",
1236 safe_str(database[e.item][ADDRESS]),
1237 safe_str(database[e.item][ADDRESS2]),
1238 safe_str(database[e.item][CITY]),
1239 safe_str(database[e.item][STATE]),
1240 safe_str(database[e.item][ZIP]),
1241 safe_str(database[e.item][COUNTRY])
1244 if (database[e.item][PHONE])
1245 fprintf(out, "TEL;HOME:%s\n", database[e.item][PHONE]);
1246 if (database[e.item][WORKPHONE])
1247 fprintf(out, "TEL;WORK:%s\n", database[e.item][WORKPHONE]);
1248 if (database[e.item][FAX])
1249 fprintf(out, "TEL;FAX:%s\n", database[e.item][FAX]);
1250 if (database[e.item][MOBILEPHONE])
1251 fprintf(out, "TEL;CELL:%s\n", database[e.item][MOBILEPHONE]);
1253 if ( database[e.item][EMAIL] ) {
1254 split_emailstr(e.item, emails);
1255 for(j=0; j < MAX_EMAILS ; j++) {
1257 fprintf(out, "EMAIL;INTERNET:%s\n",
1262 if ( database[e.item][NOTES] )
1263 fprintf(out, "NOTE:%s\n", database[e.item][NOTES]);
1264 if (database[e.item][URL])
1265 fprintf(out, "URL:%s\n", database[e.item][URL]);
1267 fprintf(out, "END:VCARD\n\n");
1275 * end of GnomeCard export filter
1280 * mutt alias export filter
1284 mutt_alias_genalias(int i)
1288 if(database[i][NICK])
1289 return strdup(database[i][NICK]);
1291 tmp = strdup(database[i][NAME]);
1293 if( ( pos = strchr(tmp, ' ') ) )
1302 mutt_alias_export(FILE *out, struct db_enumerator e)
1304 char email[MAX_EMAIL_LEN];
1307 db_enumerate_items(e) {
1308 alias = mutt_alias_genalias(e.item);
1310 get_first_email(email, e.item);
1311 fprintf(out, *email ? "alias %s %s <%s>\n": "alias %s %s%s\n",
1313 database[e.item][NAME],
1322 * end of mutt alias export filter
1327 * printable export filter
1332 text_write_address_us(FILE *out, int i) {
1333 fprintf(out, "\n%s", database[i][ADDRESS]);
1335 if (database[i][ADDRESS2])
1336 fprintf(out, "\n%s", database[i][ADDRESS2]);
1338 if (database[i][CITY])
1339 fprintf(out, "\n%s", database[i][CITY]);
1341 if (database[i][STATE] || database[i][ZIP]) {
1344 if(database[i][STATE]) {
1345 fprintf(out, "%s", database[i][STATE]);
1346 if(database[i][ZIP])
1350 if(database[i][ZIP])
1351 fprintf(out, "%s", database[i][ZIP]);
1354 if (database[i][COUNTRY])
1355 fprintf(out, "\n%s", database[i][COUNTRY]);
1360 text_write_address_uk(FILE *out, int i) {
1363 for (j = ADDRESS; j <= COUNTRY; j++)
1365 fprintf(out, "\n%s", database[i][j]);
1369 text_write_address_eu(FILE *out, int i) {
1370 fprintf(out, "\n%s", database[i][ADDRESS]);
1372 if (database[i][ADDRESS2])
1373 fprintf(out, "\n%s", database[i][ADDRESS2]);
1375 if (database[i][ZIP] || database[i][CITY]) {
1378 if(database[i][ZIP]) {
1379 fprintf(out, "%s", database[i][ZIP]);
1380 if(database[i][CITY])
1384 if(database[i][CITY])
1385 fprintf(out, "%s", database[i][CITY]);
1388 if (database[i][STATE])
1389 fprintf(out, "\n%s", database[i][STATE]);
1391 if (database[i][COUNTRY])
1392 fprintf(out, "\n%s", database[i][COUNTRY]);
1396 text_export_database(FILE * out, struct db_enumerator e)
1398 char emails[MAX_EMAILS][MAX_EMAIL_LEN];
1400 char *realname = get_real_name();
1401 char *style = options_get_str("address_style");
1404 "-----------------------------------------\n%s's address book\n"
1405 "-----------------------------------------\n\n\n",
1409 db_enumerate_items(e) {
1411 "-----------------------------------------\n\n");
1412 fprintf(out, "%s", database[e.item][NAME]);
1413 if (database[e.item][NICK])
1414 fprintf(out, "\n(%s)", database[e.item][NICK]);
1417 if (*database[e.item][EMAIL]) {
1419 split_emailstr(e.item, emails);
1420 for (j = 0; j < MAX_EMAILS; j++)
1422 fprintf(out, "%s\n", emails[j]);
1425 if (database[e.item][ADDRESS]) {
1426 if (!safe_strcmp(style, "us")) /* US like */
1427 text_write_address_us(out, e.item);
1428 else if (!safe_strcmp(style, "uk")) /* UK like */
1429 text_write_address_uk(out, e.item);
1431 text_write_address_eu(out, e.item);
1436 if ((database[e.item][PHONE]) ||
1437 (database[e.item][WORKPHONE]) ||
1438 (database[e.item][FAX]) ||
1439 (database[e.item][MOBILEPHONE])) {
1441 for (j = PHONE; j <= MOBILEPHONE; j++)
1442 if (database[e.item][j])
1443 fprintf(out, "%s: %s\n",
1444 abook_fields[j].name,
1445 database[e.item][j]);
1448 if (database[e.item][URL])
1449 fprintf(out, "\n%s\n", database[e.item][URL]);
1450 if (database[e.item][NOTES])
1451 fprintf(out, "\n%s\n", database[e.item][NOTES]);
1456 fprintf(out, "-----------------------------------------\n");
1462 * end of printable export filter
1466 * elm alias export filter
1470 elm_alias_export(FILE *out, struct db_enumerator e)
1472 char email[MAX_EMAIL_LEN];
1475 db_enumerate_items(e) {
1476 alias = mutt_alias_genalias(e.item);
1477 get_first_email(email, e.item);
1478 fprintf(out, "%s = %s = %s\n",
1480 database[e.item][NAME],
1489 * end of elm alias export filter
1494 * Spruce export filter
1498 spruce_export_database (FILE *out, struct db_enumerator e)
1500 char email[MAX_EMAIL_LEN];
1502 fprintf (out, "# This is a generated file made by abook for the Spruce e-mail client.\n\n");
1504 db_enumerate_items(e) {
1505 if(strcmp (safe_str(database[e.item][EMAIL]), "")) {
1506 get_first_email(email, e.item);
1507 fprintf(out, "# Address %d\nName: %s\nEmail: %s\nMemo: %s\n\n",
1509 database[e.item][NAME],
1511 safe_str(database[e.item][NOTES])
1516 fprintf (out, "# End of address book file.\n");
1522 * end of Spruce export filter