X-Git-Url: https://git.deb.at/w?a=blobdiff_plain;f=filter.c;h=a0bc2e485f4a120f9b154d135691a5101768900f;hb=f0d50589db0f5b8942b15995e97374dd58e53cb8;hp=a4399399b168d267d47b4ed18374c501b77afc8a;hpb=49aa0214d72eb609845e292772819de414034c55;p=pkg%2Fabook.git diff --git a/filter.c b/filter.c index a439939..a0bc2e4 100644 --- a/filter.c +++ b/filter.c @@ -2,7 +2,7 @@ /* * $Id$ * - * by JH + * by JH * * Copyright (C) Jaakko Heinonen */ @@ -21,6 +21,7 @@ #include "list.h" #include "misc.h" #include "options.h" +#include extern int items; extern list_item *database; @@ -37,6 +38,7 @@ extern struct abook_field abook_fields[]; 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); /* * export filter prototypes @@ -61,6 +63,7 @@ struct abook_input_filter i_filters[] = { { "ldif", "ldif / Netscape addressbook", ldif_parse_file }, { "mutt", "mutt alias (beta)", mutt_parse_file }, { "pine", "pine addressbook", pine_parse_file }, + { "csv", "comma separated values", csv_parse_file }, { "\0", NULL, NULL } }; @@ -412,10 +415,6 @@ export(char filtname[FILTNAME_LEN], char *filename) static void ldif_fix_string(char *str); -#ifndef LINESIZE -# define LINESIZE 1024 -#endif - #define LDIF_ITEM_FIELDS 15 typedef char* ldif_item[LDIF_ITEM_FIELDS]; @@ -460,36 +459,39 @@ static int ldif_conv_table[LDIF_ITEM_FIELDS] = { static char * ldif_read_line(FILE *in) { - char line[LINESIZE]; - char *buf=NULL; + char *buf = NULL; char *ptr, *tmp; long pos; int i; - for(i=1;;i++) { + for(i = 1;;i++) { + char *line; + pos = ftell(in); - fgets(line, LINESIZE, in); + line = getaline(in); - if( feof(in) ) + if( feof(in) || !line ) break; if(i == 1) { - buf = strdup(line); + buf = line; continue; } if(*line != ' ') { fseek(in, pos, SEEK_SET); + free(line); break; } - ptr = (char *)&line; + ptr = line; while( *ptr == ' ') ptr++; tmp = buf; buf = strconcat(buf, ptr, NULL); free(tmp); + free(line); } if( *buf == '#' ) { @@ -497,12 +499,6 @@ ldif_read_line(FILE *in) return NULL; } - if(buf) { - int i,j; - for(i=0,j=0; j < strlen(buf); i++, j++) - buf[i] = buf[j] == '\n' ? buf[++j] : buf[j]; - } - return buf; } @@ -611,29 +607,21 @@ enum { MUTT_EMAIL }; -static void -remove_newlines(char *buf) -{ - int i,j; - - for(i=0,j=0; j < strlen(buf); i++, j++) - buf[i] = buf[j] == '\n' ? buf[++j] : buf[j]; -} - static int mutt_read_line(FILE *in, char **alias, char **rest) { - char line[LINESIZE]; - char *ptr=(char *)&line; + char *line; + char *ptr; char *tmp; - fgets(line, LINESIZE, in); - remove_newlines(line); + if( !(line = ptr = getaline(in)) ) + return 1; /* error / EOF */ while( ISSPACE(*ptr) ) ptr++; if( strncmp("alias", ptr, 5) ) { + free(line); return 1; } @@ -647,8 +635,10 @@ mutt_read_line(FILE *in, char **alias, char **rest) while( ! ISSPACE(*ptr) ) ptr++; - if( (*alias = (char *)malloc(ptr-tmp+1)) == NULL) + if( (*alias = (char *)malloc(ptr-tmp+1)) == NULL) { + free(line); return 1; + } strncpy(*alias, tmp, ptr-tmp); *(*alias+(ptr-tmp)) = 0; @@ -657,7 +647,8 @@ mutt_read_line(FILE *in, char **alias, char **rest) ptr++; *rest = strdup(ptr); - + + free(line); return 0; } @@ -713,11 +704,9 @@ mutt_parse_file(FILE *in) memset(mutt_item, 0, sizeof(mutt_item) ); - if( mutt_read_line(in, &mutt_item[MUTT_ALIAS], + if( !mutt_read_line(in, &mutt_item[MUTT_ALIAS], &mutt_item[MUTT_NAME]) ) - continue; - - mutt_parse_email(mutt_item); + mutt_parse_email(mutt_item); if( feof(in) ) { free(mutt_item[MUTT_ALIAS]); @@ -946,23 +935,24 @@ static int pine_parse_file(FILE *in) { char line[LINESIZE]; - char *buf=NULL; + char *buf = NULL; char *ptr; int i; fgets(line, LINESIZE, in); while(!feof(in)) { - for(i=2;;i++) { + for(i = 2;;i++) { buf = (char *) realloc(buf, i*LINESIZE); - if(i==2) + if(i == 2) strcpy(buf, line); fgets(line, LINESIZE, in); ptr=(char *)&line; if(*ptr != ' ' || feof(in) ) break; else - while( *ptr == ' ') ptr++; + while( *ptr == ' ') + ptr++; strcat(buf, ptr); } @@ -1013,6 +1003,173 @@ pine_export_database(FILE *out, struct db_enumerator e) */ +/* + * csv import filter + */ + +/* FIXME + * these files should be parsed according to a certain + * lay out, or the default if layout is not given, at + * the moment only default is done... + */ + +#define CSV_COMMENT_CHAR '#' + +static int csv_conv_table[] = { + NAME, + EMAIL, + PHONE, + NOTES, + NICK +}; + +static void +csv_convert_emails(char *s) +{ + int i; + char *tmp; + + if( s == NULL ) + return; + + for(i=1; ( tmp = strchr(s, ',') ) != NULL ; i++, s = tmp + 1 ) + if( i > MAX_EMAILS - 1 ) { + *tmp = 0; + break; + } + +} + +static char * +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) { + my_free(copy); + return NULL; + } + trimmed[len - 1] = 0; + trimmed++; + trimmed = strdup(trimmed); + free(copy); + return trimmed; + } + + my_free(copy); + return strdup(s); +} + +static void +csv_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 < (sizeof(csv_conv_table) / sizeof(*csv_conv_table)) + && csv_conv_table[field] >= 0) { + item[csv_conv_table[field]] = newstr; + } +} + +static int +csv_is_valid_quote_end(char *p) +{ + if(*p != '\"') + return FALSE; + + for(p++; *p; p++) { + if(*p == ',') + return TRUE; + else if(!ISSPACE(*p)) + return FALSE; + } + + return TRUE; +} + +static int +csv_is_valid_quote_start(char *p) +{ + for(; *p; p++) { + if(*p == '\"') + return TRUE; + else if(!ISSPACE(*p)) + return FALSE; + } + + return FALSE; +} + +static void +csv_parse_line(char *line) +{ + char *p, *start; + int field; + int 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; + csv_store_field(item, start, field); + field++; + start = p + 1; + } + } + /* + * store last field + */ + csv_store_field(item, start, field); + + csv_convert_emails(item[EMAIL]); + add_item2database(item); +} + + +static int +csv_parse_file(FILE *in) +{ + char *line = NULL; + + while(!feof(in)) { + line = getaline(in); + + if(line && *line && *line != CSV_COMMENT_CHAR) + csv_parse_line(line); + + my_free(line); + } + + return 0; +} + +/* + * end of csv import filter + */ + /* * csv addressbook export filter */ @@ -1026,12 +1183,16 @@ csv_export_database(FILE *out, struct db_enumerator e) EMAIL, PHONE, NOTES, + NICK, -1 }; 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]]), ',') ? + 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]]) );