X-Git-Url: https://git.deb.at/w?a=blobdiff_plain;f=filter.c;h=9f62171f0f93e4ad122e63494fea928fcb4b7af1;hb=c5d8ef5198f2bfd02f678b7a709b6538ef83cd44;hp=902c481485e872305197b3a5451434638b436b43;hpb=7dca83329bb3ce545d6d03e10754999b9a82ca01;p=pkg%2Fabook.git diff --git a/filter.c b/filter.c index 902c481..9f62171 100644 --- a/filter.c +++ b/filter.c @@ -1,6 +1,6 @@ /* - * $Id: filter.c,v 1.15 2002/01/19 11:07:02 jheinonen Exp $ + * $Id: filter.c,v 1.31 2004/06/30 19:48:28 jheinonen Exp $ * * by JH * @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include #include "abook_curses.h" #include "filter.h" #include "abook.h" @@ -40,6 +40,7 @@ static int ldif_parse_file(FILE *handle); static int mutt_parse_file(FILE *in); static int pine_parse_file(FILE *in); static int csv_parse_file(FILE *in); +static int allcsv_parse_file(FILE *in); /* * export filter prototypes @@ -49,6 +50,8 @@ static int ldif_export_database(FILE *out, struct db_enumerator e); static int html_export_database(FILE *out, struct db_enumerator e); static int pine_export_database(FILE *out, struct db_enumerator e); static int csv_export_database(FILE *out, struct db_enumerator e); +static int allcsv_export_database(FILE *out, struct db_enumerator e); +static int palm_export_database(FILE *out, struct db_enumerator e); static int gcrd_export_database(FILE *out, struct db_enumerator e); static int mutt_alias_export(FILE *out, struct db_enumerator e); static int elm_alias_export(FILE *out, struct db_enumerator e); @@ -65,6 +68,7 @@ struct abook_input_filter i_filters[] = { { "mutt", "mutt alias", mutt_parse_file }, { "pine", "pine addressbook", pine_parse_file }, { "csv", "comma separated values", csv_parse_file }, + { "allcsv", "comma separated all values", allcsv_parse_file }, { "\0", NULL, NULL } }; @@ -76,6 +80,8 @@ struct abook_output_filter e_filters[] = { { "pine", "pine addressbook", pine_export_database }, { "gcrd", "GnomeCard (VCard) addressbook", gcrd_export_database }, { "csv", "comma separated values", csv_export_database }, + { "allcsv", "comma separated all values", allcsv_export_database }, + { "palmcsv", "Palm comma separated values", palm_export_database}, { "elm", "elm alias", elm_alias_export }, { "text", "plain text", text_export_database }, { "spruce", "Spruce address book", spruce_export_database }, @@ -138,7 +144,7 @@ get_real_name() pwent = getpwnam(username); - if( (tmp = (char *)malloc(strlen(pwent->pw_gecos) +1)) == NULL) + if((tmp = strdup(pwent->pw_gecos)) == NULL) return strdup(username); rtn = sscanf(pwent->pw_gecos, "%[^,]", tmp); @@ -194,7 +200,7 @@ import_database() mvaddstr(5+filter, 2, "->"); - filename = ask_filename("Filename: ", 1); + filename = ask_filename("Filename: "); if( !filename ) { refresh_screen(); return 2; @@ -202,8 +208,7 @@ import_database() if( i_read_file(filename, i_filters[filter].func ) ) statusline_msg("Error occured while opening the file"); - else - if( tmp == items ) + else if( tmp == items ) statusline_msg("Hmm.., file seems not to be a valid file"); refresh_screen(); @@ -231,14 +236,15 @@ i_read_file(char *filename, int (*func) (FILE *in)) } int -import(char filtname[FILTNAME_LEN], char *filename) +import_file(char filtname[FILTNAME_LEN], char *filename) { int i; int tmp = items; int ret = 0; for(i=0;; i++) { - if( ! strncmp(i_filters[i].filtname, filtname, FILTNAME_LEN) ) + if( ! strncasecmp(i_filters[i].filtname, filtname, + FILTNAME_LEN) ) break; if( ! *i_filters[i].filtname ) { i = -1; @@ -304,7 +310,7 @@ export_database() filter = getch() - 'a'; if(filter == 'x' - 'a' || - filter >= number_of_output_filters(e_filters) || filter < 0) { + filter >= number_of_output_filters() || filter < 0) { refresh_screen(); return 1; } @@ -324,7 +330,7 @@ export_database() clear_statusline(); } - filename = ask_filename("Filename: ", 0); + filename = ask_filename("Filename: "); if( !filename ) { refresh_screen(); return 2; @@ -367,7 +373,8 @@ fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode) struct db_enumerator e = init_db_enumerator(enum_mode); for(i=0;; i++) { - if( ! strncmp(e_filters[i].filtname, filtname, FILTNAME_LEN) ) + if( ! strncasecmp(e_filters[i].filtname, filtname, + FILTNAME_LEN) ) break; if( ! *e_filters[i].filtname ) { i = -1; @@ -378,10 +385,10 @@ fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode) return (e_filters[i].func) (handle, e); } - + int -export(char filtname[FILTNAME_LEN], char *filename) +export_file(char filtname[FILTNAME_LEN], char *filename) { const int mode = ENUM_ALL; int i; @@ -389,7 +396,8 @@ export(char filtname[FILTNAME_LEN], char *filename) struct db_enumerator e = init_db_enumerator(mode); for(i=0;; i++) { - if( ! strncmp(e_filters[i].filtname, filtname, FILTNAME_LEN) ) + if( ! strncasecmp(e_filters[i].filtname, filtname, + FILTNAME_LEN) ) break; if( ! *e_filters[i].filtname ) { i = -1; @@ -484,9 +492,9 @@ ldif_read_line(FILE *in) buf = line; continue; } - + if(*line != ' ') { - fseek(in, pos, SEEK_SET); + fseek(in, pos, SEEK_SET); /* fixme ! */ free(line); break; } @@ -505,7 +513,7 @@ ldif_read_line(FILE *in) free(buf); return NULL; } - + return buf; } @@ -516,10 +524,10 @@ ldif_add_item(ldif_item ldif_item) int i; memset(abook_item, 0, sizeof(abook_item)); - + if( !ldif_item[LDIF_ITEM_FIELDS -1] ) goto bail_out; - + for(i=0; i < LDIF_ITEM_FIELDS; i++) { if(ldif_conv_table[i] >= 0 && ldif_item[i] && *ldif_item[i] ) @@ -574,7 +582,7 @@ ldif_parse_file(FILE *handle) my_free(line); continue; /* just skip the errors */ } - + ldif_fix_string(value); ldif_convert(item, type, value); @@ -592,7 +600,7 @@ ldif_fix_string(char *str) { int i, j; - for( i = 0, j = 0; j < strlen(str); i++, j++) + for( i = 0, j = 0; j < (int)strlen(str); i++, j++) str[i] = ( str[j] == (char)0xc3 ? (char) str[++j] + (char) 0x40 : str[j] ); @@ -614,6 +622,7 @@ static int mutt_read_line(FILE *in, char **alias, char **rest) { char *line, *ptr, *tmp; + size_t alias_len; if( !(line = ptr = getaline(in)) ) return 1; /* error / EOF */ @@ -625,7 +634,7 @@ mutt_read_line(FILE *in, char **alias, char **rest) free(line); return 1; } - + ptr += 5; while( ISSPACE(*ptr) ) @@ -636,15 +645,18 @@ mutt_read_line(FILE *in, char **alias, char **rest) while( ! ISSPACE(*ptr) ) ptr++; - if( (*alias = (char *)malloc(ptr-tmp+1)) == NULL) { + /* includes also the trailing zero */ + alias_len = (size_t)(ptr - tmp + 1); + + if( (*alias = (char *)malloc(alias_len)) == NULL) { free(line); return 1; } - strncpy(*alias, tmp, ptr-tmp); - *(*alias + (ptr - tmp)) = 0; + strncpy(*alias, tmp, alias_len - 1); + *(*alias + alias_len - 1) = 0; - while( ISSPACE(*ptr) ) + while(ISSPACE(*ptr)) ptr++; *rest = strdup(ptr); @@ -653,14 +665,38 @@ mutt_read_line(FILE *in, char **alias, char **rest) return 0; } +static void +mutt_fix_quoting(char *p) +{ + char *escape = 0; + + for(; *p; p++) { + switch(*p) { + case '\"': + if(escape) + *escape = ' '; + break; + case '\\': + escape = p; + break; + default: + escape = 0; + } + } +} + static void mutt_parse_email(list_item item) { char *line = item[NAME]; - char *start = line, *tmp; + char *tmp; char *name, *email; +#if 0 + char *start = line; int i = 0; +#endif + mutt_fix_quoting(line); tmp = strconcat("From: ", line, NULL); getname(tmp, &name, &email); free(tmp); @@ -673,7 +709,11 @@ mutt_parse_email(list_item item) item[EMAIL] = email; else return; - + + /* + * this is completely broken + */ +#if 0 while( (start = strchr(start, ',')) && i++ < MAX_EMAILS - 1) { tmp = strconcat("From: ", ++start, NULL); getname(tmp, &name, &email); @@ -689,6 +729,7 @@ mutt_parse_email(list_item item) } } } +#endif } static int @@ -698,7 +739,7 @@ mutt_parse_file(FILE *in) for(;;) { memset(item, 0, sizeof(item)); - + if( !mutt_read_line(in, &item[NICK], &item[NAME]) ) mutt_parse_email(item); @@ -781,11 +822,12 @@ ldif_export_database(FILE *out, struct db_enumerator e) static void html_export_write_head(FILE *out, int extra_column); static void html_export_write_tail(FILE *out); +extern int extra_column; + static int html_export_database(FILE *out, struct db_enumerator e) { char tmp[MAX_EMAILSTR_LEN]; - int extra_column = options_get_int("extra_column"); if( items < 1 ) return 2; @@ -822,14 +864,13 @@ html_export_write_head(FILE *out, int extra_column) { char *realname = get_real_name(); - fprintf(out, "\n"); - fprintf(out, "\n\n %s's addressbook", - realname ); + fprintf(out, "\n"); + fprintf(out, "\n\n %s's addressbook", realname ); fprintf(out, "\n\n\n"); fprintf(out, "\n

%s's addressbook

\n", realname ); fprintf(out, "

\n\n"); - fprintf(out, "
\n"); + fprintf(out, "
\n"); fprintf(out, "\n\n\n", abook_fields[extra_column].name); @@ -839,7 +880,7 @@ html_export_write_head(FILE *out, int extra_column) static void html_export_write_tail(FILE *out) { - fprintf(out, "\n
NameE-mail address(es)%s
\n"); + fprintf(out, "\n\n"); fprintf(out, "\n\n\n"); } @@ -852,12 +893,14 @@ html_export_write_tail(FILE *out) * pine addressbook import filter */ +#define PINE_BUF_SIZE 2048 + static void pine_fixbuf(char *buf) { int i,j; - for(i=0,j=0; j < strlen(buf); i++, j++) + for(i=0,j=0; j < (int)strlen(buf); i++, j++) buf[i] = buf[j] == '\n' ? buf[++j] : buf[j]; } @@ -875,7 +918,7 @@ pine_convert_emails(char *s) if( ( tmp = strchr(s,')')) ) *tmp=0; - + for(i=1; ( tmp = strchr(s, ',') ) != NULL ; i++, s=tmp+1 ) if( i > MAX_EMAILS - 1 ) { *tmp = 0; @@ -890,7 +933,7 @@ pine_parse_buf(char *buf) list_item item; char *start = buf; char *end; - char tmp[400]; + char tmp[PINE_BUF_SIZE]; int i, len, last; int pine_conv_table[]= {NICK, NAME, EMAIL, -1, NOTES}; @@ -899,23 +942,24 @@ pine_parse_buf(char *buf) for(i=0, last=0; !last ; i++) { if( ! (end = strchr(start, '\t')) ) last=1; - + len = last ? strlen(start) : (int) (end-start); - len = min(len, 400-1); - - if(i < sizeof(pine_conv_table) / sizeof(*pine_conv_table) + len = min(len, PINE_BUF_SIZE - 1); + + if(i < (int)(sizeof(pine_conv_table) / sizeof(*pine_conv_table)) && pine_conv_table[i] >= 0) { strncpy(tmp, start, len); tmp[len] = 0; - item[pine_conv_table[i]] = strdup(tmp); + if(*tmp) + item[pine_conv_table[i]] = strdup(tmp); } start = end + 1; } - + pine_convert_emails(item[EMAIL]); add_item2database(item); } - + #define LINESIZE 1024 @@ -928,7 +972,7 @@ pine_parse_file(FILE *in) int i; fgets(line, LINESIZE, in); - + while(!feof(in)) { for(i = 2;;i++) { buf = (char *) realloc(buf, i*LINESIZE); @@ -941,7 +985,7 @@ pine_parse_file(FILE *in) else while( *ptr == ' ') ptr++; - + strcat(buf, ptr); } if( *buf == '#' ) { @@ -1011,6 +1055,29 @@ static int csv_conv_table[] = { NICK }; +static int allcsv_conv_table[] = { + NAME, + EMAIL, + ADDRESS, + ADDRESS2, + CITY, + STATE, + ZIP, + COUNTRY, + PHONE, + WORKPHONE, + FAX, + MOBILEPHONE, + NICK, + URL, + NOTES, + CUSTOM1, + CUSTOM2, + CUSTOM3, + CUSTOM4, + CUSTOM5, +}; + static void csv_convert_emails(char *s) { @@ -1033,10 +1100,10 @@ csv_remove_quotes(char *s) { char *copy, *trimmed; int len; - + copy = trimmed = strdup(s); strtrim(trimmed); - + len = strlen(trimmed); if(trimmed[len - 1] == '\"' && *trimmed == '\"') { if(len < 3) { @@ -1065,9 +1132,30 @@ csv_store_field(list_item item, char *s, int field) if( !(newstr = csv_remove_quotes(s)) ) return; - if(field < (sizeof(csv_conv_table) / sizeof(*csv_conv_table)) + if(field < (int)(sizeof(csv_conv_table) / sizeof(*csv_conv_table)) && csv_conv_table[field] >= 0) { item[csv_conv_table[field]] = newstr; + } else { + my_free(newstr); + } +} + +static void +allcsv_store_field(list_item item, char *s, int field) +{ + char *newstr = NULL; + + if(!s || !*s) + return; + + if( !(newstr = csv_remove_quotes(s)) ) + return; + + if(field < (int)(sizeof(allcsv_conv_table) / sizeof(*allcsv_conv_table)) + && allcsv_conv_table[field] >= 0) { + item[allcsv_conv_table[field]] = newstr; + } else { + my_free(newstr); } } @@ -1105,7 +1193,7 @@ csv_parse_line(char *line) { char *p, *start; int field; - int in_quote = FALSE; + bool in_quote = FALSE; list_item item; memset(item, 0, sizeof(item)); @@ -1136,6 +1224,42 @@ csv_parse_line(char *line) add_item2database(item); } +static void +allcsv_parse_line(char *line) +{ + char *p, *start; + int field; + bool in_quote = FALSE; + list_item item; + + memset(item, 0, sizeof(item)); + + for(p = start = line, field = 0; *p; p++) { + if(in_quote) { + if(csv_is_valid_quote_end(p)) + in_quote = FALSE; + } else { + if ( (((p - start) / sizeof (char)) < 2 ) && + csv_is_valid_quote_start(p) ) + in_quote = TRUE; + } + + if( *p == ',' && !in_quote) { + *p = 0; + allcsv_store_field(item, start, field); + field++; + start = p + 1; + } + } + /* + * store last field + */ + allcsv_store_field(item, start, field); + + csv_convert_emails(item[EMAIL]); + add_item2database(item); +} + static int csv_parse_file(FILE *in) @@ -1154,51 +1278,223 @@ csv_parse_file(FILE *in) return 0; } +static int +allcsv_parse_file(FILE *in) +{ + char *line = NULL; + + while(!feof(in)) { + line = getaline(in); + + if(line && *line && *line != CSV_COMMENT_CHAR) + allcsv_parse_line(line); + + my_free(line); + } + + return 0; +} + /* * end of csv import filter */ /* - * csv addressbook export filter + * csv addressbook export filters */ +#define CSV_LAST (-1) +#define CSV_UNDEFINED (-2) +#define CSV_SPECIAL(X) (-3 - (X)) +#define CSV_IS_SPECIAL(X) ((X) <= -3) + +static int +csv_export_common(FILE *out, struct db_enumerator e, + int fields[], void (*special_func)(FILE *, int, int)) +{ + int i; + + db_enumerate_items(e) { + for(i = 0; fields[i] != CSV_LAST; i++) { + if(fields[i] == CSV_UNDEFINED) + fprintf(out, "\"\""); + else if(CSV_IS_SPECIAL(fields[i])) { + if(special_func) + (*special_func)(out, e.item, fields[i]); + } else + /*fprintf(out,( + strchr(safe_str(database[e.item][fields[i]]), ',') || + strchr(safe_str(database[e.item][fields[i]]), '\"')) ? + "\"%s\"" : "%s", + safe_str(database[e.item][fields[i]]) + );*/ + fprintf(out, "\"%s\"", + safe_str(database[e.item][fields[i]])); + + if(fields[i + 1] != CSV_LAST) + fputc(',', out); + } + fputc('\n', out); + } + + return 0; +} + static int csv_export_database(FILE *out, struct db_enumerator e) { - int j; int csv_export_fields[] = { NAME, EMAIL, PHONE, NOTES, NICK, - -1 + CSV_LAST }; - db_enumerate_items(e) { - for(j = 0; csv_export_fields[j] >= 0; j++) { - fprintf(out,( - strchr(safe_str(database[e.item][csv_export_fields[j]]), ',') || - strchr(safe_str(database[e.item][csv_export_fields[j]]), '\"') - ) ? - "\"%s\"" : "%s", - safe_str(database[e.item][csv_export_fields[j]]) - ); - if(csv_export_fields[j+1] >= 0) - fputc(',', out); - } - fputc('\n', out); - } - + csv_export_common(out, e, csv_export_fields, NULL); + + return 0; +} +static int +allcsv_export_database(FILE *out, struct db_enumerator e) +{ + /* + * TODO: Should get these atomatically from abook_fileds + * - JH + */ + int allcsv_export_fields[] = { + NAME, + EMAIL, + ADDRESS, + ADDRESS2, + CITY, + STATE, + ZIP, + COUNTRY, + PHONE, + WORKPHONE, + FAX, + MOBILEPHONE, + NICK, + URL, + NOTES, + CUSTOM1, + CUSTOM2, + CUSTOM3, + CUSTOM4, + CUSTOM5, + CSV_LAST + }; + fprintf(out, "#"); + fprintf(out, "\"NAME\","); + fprintf(out, "\"EMAIL\","); + fprintf(out, "\"ADDRESS\","); + fprintf(out, "\"ADDRESS2\","); + fprintf(out, "\"CITY\","); + fprintf(out, "\"STATE\","); + fprintf(out, "\"ZIP\","); + fprintf(out, "\"COUNTRY\","); + fprintf(out, "\"PHONE\","); + fprintf(out, "\"WORKPHONE\","); + fprintf(out, "\"FAX\","); + fprintf(out, "\"MOBILEPHONE\","); + fprintf(out, "\"NICK\","); + fprintf(out, "\"URL\","); + fprintf(out, "\"NOTES\","); + fprintf(out, "\"CUSTOM1\","); + fprintf(out, "\"CUSTOM2\","); + fprintf(out, "\"CUSTOM3\","); + fprintf(out, "\"CUSTOM4\","); + fprintf(out, "\"CUSTOM5\"\n"); + + csv_export_common(out, e, allcsv_export_fields, NULL); + return 0; } /* - * end of csv export filter + * palm csv */ +#define PALM_CSV_NAME CSV_SPECIAL(0) +#define PALM_CSV_END CSV_SPECIAL(1) +#define PALM_CSV_CAT CSV_SPECIAL(2) + +static void +palm_split_and_write_name(FILE *out, char *name) +{ + char *p; + + assert(name); + + if ( (p = strchr(name, ' ')) ) { + /* + * last name first + */ + fprintf(out, "\"%s\",\"" , p + 1); + fwrite((void *)name, p - name, sizeof(char), out); + fputc('\"', out); + } else { + fprintf(out, "\"%s\"", safe_str(name)); + } +} + +static void +palm_csv_handle_specials(FILE *out, int item, int field) +{ + switch(field) { + case PALM_CSV_NAME: + palm_split_and_write_name(out, database[item][NAME]); + break; + case PALM_CSV_CAT: + fprintf(out, "\"abook\""); + break; + case PALM_CSV_END: + fprintf(out, "\"0\""); + break; + default: + assert(0); + } +} + +static int +palm_export_database(FILE *out, struct db_enumerator e) +{ + int palm_export_fields[] = { + PALM_CSV_NAME, /* LASTNAME, FIRSTNAME */ + CSV_UNDEFINED, /* TITLE */ + CSV_UNDEFINED, /* COMPANY */ + WORKPHONE, /* WORK PHONE */ + PHONE, /* HOME PHONE */ + FAX, /* FAX */ + MOBILEPHONE, /* OTHER */ + EMAIL, /* EMAIL */ + ADDRESS, /* ADDRESS */ + CITY, /* CITY */ + STATE, /* STATE */ + ZIP, /* ZIP */ + COUNTRY, /* COUNTRY */ + NICK, /* DEFINED 1 */ + URL, /* DEFINED 2 */ + CSV_UNDEFINED, /* DEFINED 3 */ + CSV_UNDEFINED, /* DEFINED 4 */ + NOTES, /* NOTE */ + PALM_CSV_END, /* "0" */ + PALM_CSV_CAT, /* CATEGORY */ + CSV_LAST + }; + + csv_export_common(out, e, palm_export_fields, palm_csv_handle_specials); + + return 0; +} + +/* + * end of csv export filters + */ /* * GnomeCard (VCard) addressbook export filter @@ -1395,7 +1691,7 @@ text_export_database(FILE * out, struct db_enumerator e) char emails[MAX_EMAILS][MAX_EMAIL_LEN]; int j; char *realname = get_real_name(); - char *style = options_get_str("address_style"); + char *style = opt_get_str(STR_ADDRESS_STYLE); fprintf(out, "-----------------------------------------\n%s's address book\n" @@ -1407,7 +1703,7 @@ text_export_database(FILE * out, struct db_enumerator e) fprintf(out, "-----------------------------------------\n\n"); fprintf(out, "%s", database[e.item][NAME]); - if (database[e.item][NICK]) + if (database[e.item][NICK] && *database[e.item][NICK]) fprintf(out, "\n(%s)", database[e.item][NICK]); fprintf(out, "\n");