]> git.deb.at Git - pkg/abook.git/blobdiff - filter.c
- replace abook_malloc, abook_realloc and my_free with new xmalloc routines
[pkg/abook.git] / filter.c
index d699a5c6774abf6150f0f47c8a70d3d2040ddbae..e11a60e18ee9bfb35a26ead350449e67677a21cb 100644 (file)
--- a/filter.c
+++ b/filter.c
@@ -22,6 +22,7 @@
 #include "list.h"
 #include "misc.h"
 #include "options.h"
+#include "xmalloc.h"
 #include <assert.h>
 
 extern int items;
@@ -40,6 +41,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 +51,7 @@ 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);
@@ -66,6 +69,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 }
 };
 
@@ -77,6 +81,7 @@ 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 },
@@ -140,7 +145,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);
@@ -381,7 +386,7 @@ fexport(char filtname[FILTNAME_LEN], FILE *handle, int enum_mode)
        return (e_filters[i].func) (handle, e);
 }
 
-       
+
 
 int
 export_file(char filtname[FILTNAME_LEN], char *filename)
@@ -488,9 +493,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;
                }
@@ -509,7 +514,7 @@ ldif_read_line(FILE *in)
                free(buf);
                return NULL;
        }
-               
+
        return buf;
 }
 
@@ -520,10 +525,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] )
@@ -534,7 +539,7 @@ ldif_add_item(ldif_item ldif_item)
 
 bail_out:
        for(i=0; i < LDIF_ITEM_FIELDS; i++)
-               my_free(ldif_item[i]);
+               xfree(ldif_item[i]);
 
 }
 
@@ -554,7 +559,7 @@ ldif_convert(ldif_item item, char *type, char *value)
                                if( safe_strcmp("person", value))
                                        break;
                        if(item[i])
-                               my_free(item[i]);
+                               xfree(item[i]);
                        item[i] = strdup(value);
                }
        }
@@ -575,15 +580,15 @@ ldif_parse_file(FILE *handle)
                        continue;
 
                if( -1 == ( str_parse_line(line, &type, &value, &vlen)) ) {
-                       my_free(line);
+                       xfree(line);
                        continue; /* just skip the errors */
                }
-                               
+
                ldif_fix_string(value);
 
                ldif_convert(item, type, value);
 
-               my_free(line);
+               xfree(line);
        } while ( !feof(handle) );
 
        ldif_convert(item, "dn", "");
@@ -618,6 +623,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 */
@@ -629,7 +635,7 @@ mutt_read_line(FILE *in, char **alias, char **rest)
                free(line);
                return 1;
        }
-               
+
        ptr += 5;
 
        while( ISSPACE(*ptr) )
@@ -640,15 +646,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 = xmalloc(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);    
@@ -657,14 +666,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);
@@ -677,7 +710,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,10 +726,11 @@ mutt_parse_email(list_item item)
                                free(item[EMAIL]);
                                item[EMAIL] = tmp;
                        } else {
-                               my_free(email);
+                               xfree(email);
                        }
                }
        }
+#endif
 }
 
 static int
@@ -702,7 +740,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);
@@ -856,6 +894,8 @@ html_export_write_tail(FILE *out)
  * pine addressbook import filter
  */
 
+#define PINE_BUF_SIZE 2048
+
 static void
 pine_fixbuf(char *buf)
 {
@@ -879,7 +919,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;
@@ -894,32 +934,33 @@ 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};
 
-       memset(&item, 0, sizeof(item) );
+       memset(&item, 0, sizeof(item));
        
        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);
-       
+               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
 
@@ -932,10 +973,10 @@ pine_parse_file(FILE *in)
        int i;
 
        fgets(line, LINESIZE, in);      
-       
+
        while(!feof(in)) {
                for(i = 2;;i++) {
-                       buf = (char *) realloc(buf, i*LINESIZE);
+                       buf = xrealloc(buf, i*LINESIZE);
                        if(i == 2)
                                strcpy(buf, line);
                        fgets(line, LINESIZE, in);
@@ -945,18 +986,18 @@ pine_parse_file(FILE *in)
                        else
                                while( *ptr == ' ')
                                        ptr++;
-                               
+
                        strcat(buf, ptr);
                }
                if( *buf == '#' ) {
-                       my_free(buf);
+                       xfree(buf);
                        continue;
                }
                pine_fixbuf(buf);
 
                pine_parse_buf(buf);
 
-               my_free(buf);
+               xfree(buf);
        }
 
        return 0;
@@ -1015,6 +1056,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)
 {
@@ -1037,14 +1101,14 @@ 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);
+                       xfree(copy);
                        return NULL;
                }
                trimmed[len - 1] = 0;
@@ -1054,7 +1118,7 @@ csv_remove_quotes(char *s)
                return trimmed;
        }
 
-       my_free(copy);
+       xfree(copy);
        return strdup(s);
 }
 
@@ -1073,7 +1137,26 @@ csv_store_field(list_item item, char *s, int field)
                        && csv_conv_table[field] >= 0) {
                item[csv_conv_table[field]] = newstr;
        } else {
-               my_free(newstr);
+               xfree(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 {
+               xfree(newstr);
        }
 }
 
@@ -1142,6 +1225,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,7 +1273,24 @@ csv_parse_file(FILE *in)
                if(line && *line && *line != CSV_COMMENT_CHAR)
                        csv_parse_line(line);
 
-               my_free(line);
+               xfree(line);
+       }
+
+       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);
+
+               xfree(line);
        }
 
        return 0;
@@ -1165,59 +1301,132 @@ csv_parse_file(FILE *in)
  */
 
 /*
- * 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_database(FILE *out, struct db_enumerator e)
+csv_export_common(FILE *out, struct db_enumerator e,
+               int fields[], void (*special_func)(FILE *, int, int))
 {
-       int j;
-       int csv_export_fields[] = {
-               NAME,
-               EMAIL,
-               PHONE,
-               NOTES,
-               NICK,
-               -1
-       };
+       int i;
 
        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]]), '\"')
-                       ) ?
+               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][csv_export_fields[j]])
-                               );
-                       if(csv_export_fields[j+1] >= 0)
+                               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 csv_export_fields[] = {
+               NAME,
+               EMAIL,
+               PHONE,
+               NOTES,
+               NICK,
+               CSV_LAST
+       };
 
+       csv_export_common(out, e, csv_export_fields, NULL);
+       
        return 0;
 }
 
-/*
- * end of csv export filter
- */
+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;
+}
 
 /*
- * Palm csv addressbook export filter
+ * palm csv
  */
 
-/* A few contants, not the best way to init them but better dan
- * some number that will break things later on...              */
-#define        PALM_CSV_UNDEFINED       (LAST_FIELD+1)
-#define        PALM_CSV_END             (LAST_FIELD+2)
-#define        PALM_CSV_CAT             (LAST_FIELD+3)
+#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) {
+palm_split_and_write_name(FILE *out, char *name)
+{
        char *p;
 
        assert(name);
@@ -1234,14 +1443,31 @@ palm_split_and_write_name(FILE *out, char *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 j;
        int palm_export_fields[] = {
-               NAME,                   /* LASTNAME, FIRSTNAME  */
-               PALM_CSV_UNDEFINED,     /* TITLE,               */
-               PALM_CSV_UNDEFINED,     /* COMPAGNY,            */
+               PALM_CSV_NAME,          /* LASTNAME, FIRSTNAME  */
+               CSV_UNDEFINED,          /* TITLE                */
+               CSV_UNDEFINED,          /* COMPANY              */
                WORKPHONE,              /* WORK PHONE           */
                PHONE,                  /* HOME PHONE           */
                FAX,                    /* FAX                  */
@@ -1254,54 +1480,23 @@ palm_export_database(FILE *out, struct db_enumerator e)
                COUNTRY,                /* COUNTRY              */
                NICK,                   /* DEFINED 1            */
                URL,                    /* DEFINED 2            */
-               PALM_CSV_UNDEFINED,     /* DEFINED 3            */
-               PALM_CSV_UNDEFINED,     /* DEFINED 4            */
+               CSV_UNDEFINED,          /* DEFINED 3            */
+               CSV_UNDEFINED,          /* DEFINED 4            */
                NOTES,                  /* NOTE                 */
                PALM_CSV_END,           /* "0"                  */
                PALM_CSV_CAT,           /* CATEGORY             */
-               -1
+               CSV_LAST
        };
 
-       db_enumerate_items(e) {
-               for(j = 0; palm_export_fields[j] >= 0; j++) {
-
-               switch( palm_export_fields[j] ) {
-
-                       case PALM_CSV_UNDEFINED:
-                               fprintf(out, "\"\"");
-                               break;
-                       case PALM_CSV_END:
-                               fprintf(out, "\"0\"");
-                               break;
-                       case PALM_CSV_CAT:
-                               fprintf(out, "\"abook\"");
-                               break;
-                       case NAME:
-                               palm_split_and_write_name(out,
-                                               safe_str(database[e.item]
-                                               [palm_export_fields[j]])) ;
-                               break;
-
-                       default:
-                               fprintf(out, "\"%s\"" ,
-                                       safe_str(database[e.item]
-                                               [palm_export_fields[j]]));
-                       }
-
-                       if(palm_export_fields[j+1] >= 0)
-                               fputc(',', out);
-               }
-               fputc('\n', out);
-       }
+       csv_export_common(out, e, palm_export_fields, palm_csv_handle_specials);
 
        return 0;
 }
 
 /*
- * end of palm csv export filter
+ * end of csv export filters
  */
 
-
 /*
  * GnomeCard (VCard) addressbook export filter
  */
@@ -1411,7 +1606,7 @@ mutt_alias_export(FILE *out, struct db_enumerator e)
                                alias,
                                database[e.item][NAME],
                                email);
-               my_free(alias);
+               xfree(alias);
        }
 
        return 0;
@@ -1509,7 +1704,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");
 
@@ -1578,7 +1773,7 @@ elm_alias_export(FILE *out, struct db_enumerator e)
                                alias,
                                database[e.item][NAME],
                                email);
-               my_free(alias);
+               xfree(alias);
        }
 
        return 0;