static int palm_export_database(FILE *out, struct db_enumerator e);
static int vcard_export_database(FILE *out, struct db_enumerator e);
static int mutt_alias_export(FILE *out, struct db_enumerator e);
+static int mutt_query_export_database(FILE *out, struct db_enumerator e);
static int elm_alias_export(FILE *out, struct db_enumerator e);
static int text_export_database(FILE *out, struct db_enumerator e);
static int spruce_export_database(FILE *out, struct db_enumerator e);
static int wl_export_database(FILE *out, struct db_enumerator e);
static int bsdcal_export_database(FILE *out, struct db_enumerator e);
+static int custom_export_database(FILE *out, struct db_enumerator e);
/*
* end of function declarations
{ "ldif", N_("ldif / Netscape addressbook (.4ld)"), ldif_export_database },
{ "vcard", N_("vCard 2 file"), vcard_export_database },
{ "mutt", N_("mutt alias"), mutt_alias_export },
+ { "muttq", N_("mutt query format (internal use)"), mutt_query_export_database },
{ "html", N_("html document"), html_export_database },
{ "pine", N_("pine addressbook"), pine_export_database },
{ "csv", N_("comma separated values"), csv_export_database },
{ "wl", N_("Wanderlust address book"), wl_export_database },
{ "spruce", N_("Spruce address book"), spruce_export_database },
{ "bsdcal", N_("BSD calendar"), bsdcal_export_database },
+ { "custom", N_("Custom format"), custom_export_database },
{ "\0", NULL, NULL }
};
+struct abook_output_item_filter u_filters[] = {
+ { "muttq", N_("mutt alias"), muttq_print_item },
+ { "custom", N_("Custom format"), custom_print_item },
+ { "\0", NULL }
+};
+
/*
* common functions
*/
gettext(e_filters[i].desc));
putchar('\n');
+
+ puts(_("output (with query):"));
+ for(i=0; *u_filters[i].filtname ; i++)
+ printf("\t%s\t%s\n", u_filters[i].filtname,
+ gettext(u_filters[i].desc));
+
+ putchar('\n');
}
static int
return 0;
}
+struct abook_output_item_filter select_output_item_filter(char filtname[FILTNAME_LEN]) {
+ int i;
+ for(i=0;; i++) {
+ if(!strncasecmp(u_filters[i].filtname, filtname, FILTNAME_LEN))
+ break;
+ if(!*u_filters[i].filtname) {
+ i = -1;
+ break;
+ }
+ }
+ return u_filters[i];
+}
+
+void
+e_write_item(FILE *out, int item, void (*func) (FILE *in, int item))
+{
+ (*func) (out, item);
+}
+
static int
e_write_file(char *filename, int (*func) (FILE *in, struct db_enumerator e),
int mode)
#include "getname.h"
static int
-mutt_read_line(FILE *in, char **alias, char **rest)
+mutt_read_line(FILE *in, char **groups, char **alias, char **rest)
{
- char *line, *ptr, *tmp;
- size_t alias_len;
+ char *line, *ptr;
+ char *start, *end;
+ abook_list *glist = NULL;
if( !(line = ptr = getaline(in)) )
return 1; /* error / EOF */
}
ptr += 5;
-
SKIPWS(ptr);
- tmp = ptr;
-
- while( ! ISSPACE(*ptr) )
- ptr++;
-
- alias_len = (size_t)(ptr - tmp);
+ /* If the group option is used, save the groups */
+ *groups = NULL;
+ start = ptr;
+ int n_groups;
+ for(n_groups = 0; 0 == strncmp("-group", ptr, 6); n_groups++) {
+ ptr += 6;
+ SKIPWS(ptr);
+ start = ptr;
+ SKIPNONWS(ptr);
+ end = ptr;
+ abook_list_append(&glist,xstrndup(start, end - start));
+ SKIPWS(ptr);
+ }
- if(alias)
- *alias = xmalloc_inc(alias_len, 1);
+ if(n_groups && groups)
+ *groups = abook_list_to_csv(glist);
- strncpy(*alias, tmp, alias_len);
- *(*alias + alias_len) = 0;
+ abook_list_free(&glist);
+ /* alias */
+ start = ptr;
+ SKIPNONWS(ptr);
+ end = ptr;
SKIPWS(ptr);
+ if(alias)
+ *alias = xstrndup(start, end - start);
+ /* rest (email) */
*rest = xstrdup(ptr);
- free(line);
+ xfree(line);
return 0;
}
memset(item, 0, fields_count * sizeof(char *));
if(!mutt_read_line(in,
- (field_id(NICK) != -1) ?
- &item[field_id(NICK)] : NULL,
- &item[field_id(NAME)]))
+ (field_id(GROUPS) != -1) ? &item[field_id(GROUPS)] : NULL,
+ (field_id(NICK) != -1) ? &item[field_id(NICK)] : NULL,
+ &item[field_id(NAME)]) )
mutt_parse_email(item);
if(feof(in)) {
static void
vcard_parse_phone(list_item item, char *line)
{
- int index = 8;
char *type = vcard_get_line_element(line, VCARD_KEY_ATTRIBUTE);
char *value = vcard_get_line_element(line, VCARD_VALUE);
/* set the standard number */
- if (!type) {
- item[index] = value;
- }
+ if (!type) item_fput(item, PHONE, value);
/*
* see rfc2426 section 3.3.1
* Note: we probably support both vCard 2 and 3
*/
else {
- if (strcasestr(type, "home") != NULL) {
- item[index] = xstrdup(value);
- }
- if (strcasestr(type, "work") != NULL) {
- item[index+1] = xstrdup(value);
- }
- if (strcasestr(type, "fax") != NULL) {
- item[index+2] = xstrdup(value);
- }
- if (strcasestr(type, "cell") != NULL) {
- item[index+3] = xstrdup(value);
- }
+ if (strcasestr(type, "home") != NULL)
+ item_fput(item, PHONE, xstrdup(value));
+ else if (strcasestr(type, "work") != NULL)
+ item_fput(item, WORKPHONE, xstrdup(value));
+ else if (strcasestr(type, "fax") != NULL)
+ item_fput(item, FAX, xstrdup(value));
+ else if (strcasestr(type, "cell") != NULL)
+ item_fput(item, MOBILEPHONE, xstrdup(value));
xfree(type);
xfree(value);
URL,
NOTES,
ANNIVERSARY,
+ GROUPS,
CSV_LAST
};
fprintf(out, "\"NICK\",");
fprintf(out, "\"URL\",");
fprintf(out, "\"NOTES\",");
- fprintf(out, "\"ANNIVERSARY\"\n");
+ fprintf(out, "\"ANNIVERSARY\",");
+ fprintf(out, "\"GROUPS\"\n");
csv_export_common(out, e, allcsv_export_fields, NULL);
return tmp;
}
+/*
+ * This function is a variant of abook_list_to_csv
+ * */
+static char *
+mutt_alias_gengroups(int i)
+{
+ char *groups, *res = NULL;
+ char groupstr[7] = "-group ";
+ abook_list *list, *tmp;
+
+ groups = db_fget(i, GROUPS);
+
+ if(!groups)
+ return NULL;
+
+ list = csv_to_abook_list(groups);
+ for(tmp = list; tmp; tmp = tmp->next) {
+ if(tmp == list) {
+ res = xmalloc(strlen(groupstr)+strlen(tmp->data)+1);
+ res = strcpy(res, groupstr);
+ } else {
+ res = xrealloc(res, strlen(res)+1+strlen(groupstr)+strlen(tmp->data)+1);
+ strcat(res, " ");
+ strcat(res, groupstr);
+ }
+ strcat(res, tmp->data);
+ }
+ abook_list_free(&list);
+ xfree(groups);
+
+ return res;
+}
+
static int
mutt_alias_export(FILE *out, struct db_enumerator e)
{
char email[MAX_EMAIL_LEN];
char *alias = NULL;
+ char *groups = NULL;
int email_addresses;
char *ptr;
db_enumerate_items(e) {
- alias = mutt_alias_genalias(e.item);
+ alias = (field_id(NICK) != -1) ? mutt_alias_genalias(e.item) : NULL;
+ groups = (field_id(GROUPS) != -1) ? mutt_alias_gengroups(e.item) : NULL;
get_first_email(email, e.item);
/* do not output contacts without email address */
if (*email) {
/* output first email address */
- fprintf(out, "alias %s %s <%s>\n",
- alias,
+ fprintf(out,"alias ");
+ if(groups)
+ fprintf(out, "%s ", groups);
+ if(alias)
+ fprintf(out, "%s ", alias);
+ fprintf(out, "%s <%s>\n",
db_name_get(e.item),
email);
while (email_addresses-- > 1) {
roll_emails(e.item, ROTATE_RIGHT);
get_first_email(email, e.item);
- fprintf(out, "alias %s__%s %s <%s>\n",
- alias,
- email,
+ fprintf(out,"alias ");
+ if( groups )
+ fprintf(out, "%s ", groups);
+ if(alias)
+ fprintf(out, "%s__%s ", alias, email);
+ else
+ fprintf(out, "%s__%s ", db_name_get(e.item), email);
+ fprintf(out, "%s <%s>\n",
db_name_get(e.item),
email);
}
roll_emails(e.item, ROTATE_RIGHT);
xfree(alias);
+ xfree(groups);
}
}
return 0;
}
+void muttq_print_item(FILE *file, int item)
+{
+ abook_list *emails, *e;
+ char *tmp = db_email_get(item);
+
+ emails = csv_to_abook_list(tmp);
+ free(tmp);
+
+ for(e = emails; e; e = e->next) {
+ fprintf(file, "%s\t%s\t%s\n", e->data, db_name_get(item),
+ !db_fget(item, NOTES) ?" " :db_fget(item, NOTES)
+ );
+ if(!opt_get_bool(BOOL_MUTT_RETURN_ALL_EMAILS))
+ break;
+ }
+ abook_list_free(&emails);
+}
+
+static int
+mutt_query_export_database(FILE *out, struct db_enumerator e)
+{
+ fprintf(out, "All items\n");
+ db_enumerate_items(e)
+ muttq_print_item(out, e.item);
+ return 0;
+}
+
/*
* end of mutt alias export filter
*/
return 0;
}
+// see enum field_types @database.h
+static char *conv_table[] = {
+ "name",
+ "email",
+ "address",
+ "address2",
+ "city",
+ "state",
+ "zip",
+ "country",
+ "phone",
+ "workphone",
+ "fax",
+ "mobile",
+ "nick",
+ "url",
+ "notes",
+ "anniversary",
+ 0 /* ITEM_FIELDS */
+};
+
+static int
+find_field_enum(char *s) {
+ int i = 0;
+ while (conv_table[i]) {
+ if(!safe_strcmp(conv_table[i], s))
+ return i;
+ i++;
+ }
+ // failed
+ return -1;
+}
+
+/* Convert a string with named placeholders to
+ a *printf() compatible string.
+ Stores the abook field values into ft. */
+void
+parse_custom_format(char *s, char *fmt_string, enum field_types *ft)
+{
+ if(! fmt_string || ! ft) {
+ fprintf(stderr, _("parse_custom_format: fmt_string or ft not allocated\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ char *p, *start, *field_name = NULL;
+ p = start = s;
+
+ while(*p) {
+ if(*p == '{') {
+ start = ++p;
+ p = strchr(start, '}');
+ if(! *p) {
+ fprintf(stderr, _("parse_custom_format: invalid format\n"));
+ exit(EXIT_FAILURE);
+ }
+ strcat(fmt_string, "%s");
+ field_name = strndup(start, (size_t)(p-start));
+ *ft = find_field_enum(field_name);
+ if(*ft == -1) {
+ fprintf(stderr, _("parse_custom_format: invalid placeholder: {%s}\n"), field_name);
+ exit(EXIT_FAILURE);
+ }
+
+ ft++;
+ p++;
+ start = p;
+ } else {
+ p = strchr(start, '{');
+ if(p && *p) {
+ strncat(fmt_string, start, (size_t)(p-start));
+ start = p;
+ }
+ else {
+ strncat( fmt_string,
+ start,
+ FORMAT_STRING_LEN - strlen(fmt_string) - 1 );
+ break;
+ }
+ }
+ }
+ *ft = 66;
+}
+
+static int
+custom_export_item(FILE *out, int item, char *s, enum field_types *ft);
+
+
+// used to store the format string from --outformatstr when "custom" format is used
+// default value overriden in export_file()
+extern char *parsed_custom_format;
+extern enum field_types *custom_format_fields;
+
+/* wrapper for custom_export_item:
+ 1) avoid messing with extern pointer
+ 2) adds \n
+ 3) follow the prototype needed for an abook_output_item_filter entry */
+void
+custom_print_item(FILE *out, int item)
+{
+
+ if(custom_export_item(out, item, parsed_custom_format, custom_format_fields) == 0)
+ fprintf(out, "\n");
+}
+
+static int
+custom_export_item(FILE *out, int item, char *fmt, enum field_types *ft)
+{
+ char *p, *q = 0;
+
+ // if the first character is '!':
+ // we first check that all fields exist before continuing
+ if(*fmt == '!') {
+ enum field_types *ftp = ft;
+ while(*ft != 66) {
+ if(! db_fget(item, *ft) )
+ return 1;
+ ft++;
+ }
+ ft = ftp;
+ fmt++;
+ }
+
+ while (*fmt) {
+ if(!strncmp(fmt, "%s", 2)) {
+ fprintf(out, "%s", safe_str(db_fget(item, *ft)));
+ ft++;
+ fmt+=2;
+ } else if (*ft == 66) {
+ fprintf(out, "%s", fmt);
+ return 0;
+ } else {
+ p = strchr(fmt, '%');
+ if(*p) {
+ q = strndup(fmt, (size_t)(p-fmt));
+ fprintf(out, "%s", q);
+ free(q);
+ fmt = p;
+ }
+ else {
+ fprintf(out, "%s", fmt);
+ return 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+// used to store the format string from --outformatstr when "custom" format is used
+// default value overriden from abook.c
+extern char custom_format[FORMAT_STRING_LEN];
+
+static int
+custom_export_database(FILE *out, struct db_enumerator e)
+{
+ char *format_string =
+ (char *)malloc(FORMAT_STRING_LEN * sizeof(char*));
+
+ enum field_types *ft =
+ (enum field_types *)malloc(FORMAT_STRING_MAX_FIELDS * sizeof(enum field_types *));
+
+ parse_custom_format(custom_format, format_string, ft);
+
+ db_enumerate_items(e) {
+ if(custom_export_item(out, e.item, format_string, ft) == 0)
+ fprintf(out, "\n");
+ }
+ return 0;
+}
+
/*
* end of BSD calendar export filter
*/