]> git.deb.at Git - pkg/abook.git/blobdiff - filter.c
Fixed a bug in html filter
[pkg/abook.git] / filter.c
index 99d01a2b5b9c39d7084cd9cd1c2e9c8c6f5bed38..b4893983dfb40015bebf23c019c2d166dc653053 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -2,7 +2,7 @@
 /*
  * $Id$
  *
- * by JH <jheinonen@bigfoot.com>
+ * by JH <jheinonen@users.sourceforge.net>
  *
  * Copyright (C) Jaakko Heinonen
  */
@@ -21,6 +21,7 @@
 #include "list.h"
 #include "misc.h"
 #include "options.h"
+#include <assert.h>
 
 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
@@ -59,8 +61,9 @@ static int    spruce_export_database(FILE *out, struct db_enumerator e);
 struct abook_input_filter i_filters[] = {
        { "abook", "abook native format", parse_database },
        { "ldif", "ldif / Netscape addressbook", ldif_parse_file },
-       { "mutt", "mutt alias (beta)", mutt_parse_file },
+       { "mutt", "mutt alias", mutt_parse_file },
        { "pine", "pine addressbook", pine_parse_file },
+       { "csv", "comma separated values", csv_parse_file },
        { "\0", NULL, NULL }
 };
 
@@ -134,7 +137,7 @@ get_real_name()
 
        pwent = getpwnam(username);
 
-       if( (tmp = malloc(strlen(pwent->pw_gecos) +1)) == NULL)
+       if( (tmp = (char *)malloc(strlen(pwent->pw_gecos) +1)) == NULL)
                return strdup(username);
 
        rtn = sscanf(pwent->pw_gecos, "%[^,]", tmp);
@@ -412,11 +415,7 @@ 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
+#define        LDIF_ITEM_FIELDS        16
 
 typedef char*  ldif_item[LDIF_ITEM_FIELDS];
 
@@ -424,6 +423,7 @@ static ldif_item ldif_field_names = {
        "cn",   
        "mail",
        "streetaddress",
+       "streetaddress2",
         "locality",
        "st",
        "postalcode",
@@ -442,6 +442,7 @@ static int ldif_conv_table[LDIF_ITEM_FIELDS] = {
        NAME,           /* "cn" */
        EMAIL,          /* "mail" */
        ADDRESS,        /* "streetaddress" */
+       ADDRESS2,       /* "streetaddress2" */     
         CITY,          /* "locality" */
        STATE,          /* "st" */
        ZIP,            /* "postalcode" */
@@ -460,36 +461,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 +501,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;
 }
 
@@ -605,35 +603,21 @@ ldif_fix_string(char *str)
  * mutt alias import filter
  */
 
-enum {
-       MUTT_ALIAS,
-       MUTT_NAME,
-       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];
-}
+#include "getname.h"
 
 static int
 mutt_read_line(FILE *in, char **alias, char **rest)
 {
-       char line[LINESIZE];
-       char *ptr=(char *)&line;
-       char *tmp;
+       char *line, *ptr, *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,93 +631,81 @@ mutt_read_line(FILE *in, char **alias, char **rest)
        while( ! ISSPACE(*ptr) )
                ptr++;
 
-       if( (*alias = 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;
+       *(*alias + (ptr - tmp)) = 0;
 
        while( ISSPACE(*ptr) )
                ptr++;
 
        *rest = strdup(ptr);    
-       
+
+       free(line);
        return 0;
 }
 
 static void
-mutt_parse_email(char *mutt_item[3])
+mutt_parse_email(list_item item)
 {
-       char *tmp;
-       int i;
-
-       if( (tmp = strchr(mutt_item[MUTT_NAME], '<')) )
-               *tmp = 0;
-       else
-               return;
-
-       mutt_item[MUTT_EMAIL] = strdup(tmp+1);
-
-       if( (tmp = strchr(mutt_item[MUTT_EMAIL], '>')) )
-               *tmp = 0;
-
-       tmp = mutt_item[MUTT_NAME];
-
-       for(i=strlen(tmp)-1; i>0; i--)
-               if(ISSPACE(tmp[i]))
-                       tmp[i] = 0;
-               else
-                       break;
-
-       mutt_item[MUTT_NAME] = strdup(tmp);
+       char *line = item[NAME];
+       char *start = line, *tmp;
+       char *name, *email;
+       int i = 0;
 
+       tmp = strconcat("From: ", line, NULL);
+       getname(tmp, &name, &email);
        free(tmp);
-}
 
-static void
-mutt_add_mutt_item(char *mutt_item[3])
-{
-       list_item abook_item;
-
-       memset(abook_item, 0, sizeof(abook_item));
-
-       abook_item[NAME] = safe_strdup(mutt_item[MUTT_NAME]);
-       abook_item[EMAIL] = safe_strdup(mutt_item[MUTT_EMAIL]);
-       abook_item[NICK] = safe_strdup(mutt_item[MUTT_ALIAS]);
-
-       add_item2database(abook_item);
+       if(name)
+               item[NAME] = name;
+       else
+               return;
+       if(email)
+               item[EMAIL] = email;
+       else
+               return;
+       
+       while( (start = strchr(start, ',')) && i++ < MAX_EMAILS - 1) {
+               tmp = strconcat("From: ", ++start, NULL);
+               getname(tmp, &name, &email);
+               free(tmp);
+               free(name);
+               if(email) {
+                       if(*email) {
+                               tmp = strconcat(item[EMAIL], ",", email, NULL);
+                               free(item[EMAIL]);
+                               item[EMAIL] = tmp;
+                       } else {
+                               my_free(email);
+                       }
+               }
+       }
 }
 
 static int
 mutt_parse_file(FILE *in)
 {
-       char *mutt_item[3];
+       list_item item;
 
        for(;;) {
-
-               memset(mutt_item, 0, sizeof(mutt_item) );
+               memset(item, 0, sizeof(item));
                
-               if( mutt_read_line(in, &mutt_item[MUTT_ALIAS],
-                               &mutt_item[MUTT_NAME]) )
-                       continue;
-
-               mutt_parse_email(mutt_item);
+               if( !mutt_read_line(in, &item[NICK],
+                               &item[NAME]) )
+                       mutt_parse_email(item);
 
                if( feof(in) ) {
-                       free(mutt_item[MUTT_ALIAS]);
-                       free(mutt_item[MUTT_NAME]);
-                       free(mutt_item[MUTT_EMAIL]);
+                       free_list_item(item);
                        break;
                }
 
-               mutt_add_mutt_item(mutt_item);
-
-               free(mutt_item[MUTT_ALIAS]);
-               free(mutt_item[MUTT_NAME]);
-               free(mutt_item[MUTT_EMAIL]);
+               add_item2database(item);
        }
 
-
        return 0;
 }
 
@@ -825,7 +797,7 @@ html_export_database(FILE *out, struct db_enumerator e)
                            tmp,
                            database[e.item][NAME] );
                else
-                   fprintf(out, "<tr>\n<td>%s>\n",
+                   fprintf(out, "<tr>\n<td>%s\n",
                            database[e.item][NAME] );
 
                fprintf(out, "<td>%s\n<td>%s\n",
@@ -946,23 +918,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++) {
-                       buf = realloc(buf, i*LINESIZE);
-                       if(i==2)
+               for(i = 2;;i++) {
+                       buf = (char *) realloc(buf, i*LINESIZE);
+                       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 +986,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 +1166,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]])
                                );
@@ -1080,8 +1224,9 @@ gcrd_export_database(FILE *out, struct db_enumerator e)
                free(name);
 
                if ( database[e.item][ADDRESS] )
-                       fprintf(out, "ADR:;;%s;%s;%s;%s;%s\n",
+                       fprintf(out, "ADR:;;%s;%s;%s;%s;%s;%s\n",
                                safe_str(database[e.item][ADDRESS]),
+                               safe_str(database[e.item][ADDRESS2]),                           
                                safe_str(database[e.item][CITY]),
                                safe_str(database[e.item][STATE]),
                                safe_str(database[e.item][ZIP]),
@@ -1178,7 +1323,10 @@ mutt_alias_export(FILE *out, struct db_enumerator e)
 static void
 text_write_address_us(FILE *out, int i) {
        fprintf(out, "\n%s", database[i][ADDRESS]);
-       
+
+       if (database[i][ADDRESS2])
+               fprintf(out, "\n%s", database[i][ADDRESS2]);
+
        if (database[i][CITY])
                fprintf(out, "\n%s", database[i][CITY]);
                
@@ -1212,7 +1360,10 @@ text_write_address_uk(FILE *out, int i) {
 static void
 text_write_address_eu(FILE *out, int i) {
        fprintf(out, "\n%s", database[i][ADDRESS]);
-       
+
+       if (database[i][ADDRESS2])
+               fprintf(out, "\n%s", database[i][ADDRESS2]);
+
        if (database[i][ZIP] || database[i][CITY]) {
                fputc('\n', out);