diff options
Diffstat (limited to 'mail/util.c')
-rw-r--r-- | mail/util.c | 500 |
1 files changed, 328 insertions, 172 deletions
diff --git a/mail/util.c b/mail/util.c index f92f91e36..f7f242961 100644 --- a/mail/util.c +++ b/mail/util.c @@ -1,5 +1,5 @@ /* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 1999-2021 Free Software Foundation, Inc. + Copyright (C) 1999-2024 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,6 +17,8 @@ #include "mail.h" #include <mailutils/util.h> #include <mailutils/mime.h> +#include <mailutils/folder.h> +#include <mailutils/auth.h> #include <pwd.h> #ifdef HAVE_TERMIOS_H # include <termios.h> @@ -49,60 +51,55 @@ util_do_command (const char *fmt, ...) if (status) return status; - if (cmd) + /* Ignore comments */ + if (cmd[0] == '#') { - /* Ignore comments */ - if (cmd[0] == '#') - { - free (cmd); - return 0; - } - - if (cmd[0] == '\0') - { - free (cmd); + free (cmd); + return 0; + } - /* Hitting return i.e. no command, is equivalent to next - according to the POSIX spec. Note, that this applies - to interactive state only. */ - if (interactive) - cmd = mu_strdup ("next"); - else - return 0; - } + if (cmd[0] == '\0') + { + free (cmd); - ws.ws_offs = 1; /* Keep one extra slot in case we need it - for expansion (see below) */ - if (mu_wordsplit (cmd, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DOOFFS)) - { - mu_error ("\"%s\": %s", cmd, mu_wordsplit_strerror (&ws)); - free (cmd); - return MU_ERR_PARSE; - } + /* Hitting return i.e. no command, is equivalent to next + according to the POSIX spec. Note, that this applies + to interactive state only. */ + if (interactive) + cmd = mu_strdup ("next"); else - { - char *p; + return 0; + } - argc = ws.ws_wordc; - argv = ws.ws_wordv + 1; + ws.ws_offs = 1; /* Keep one extra slot in case we need it + for expansion (see below) */ + if (mu_wordsplit (cmd, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DOOFFS)) + { + mu_error ("\"%s\": %s", cmd, mu_wordsplit_strerror (&ws)); + free (cmd); + return MU_ERR_PARSE; + } + else + { + char *p; - /* Special case: a number alone implies "print" */ - if (argc == 1 - && ((strtoul (argv[0], &p, 10) > 0 && *p == 0) - || (argv[0][1] == 0 && strchr ("^$", argv[0][0])))) - { - /* Use the extra slot for "print" command */ - argc++; - argv--; - argv[0] = "print"; - } + argc = ws.ws_wordc; + argv = ws.ws_wordv + 1; - entry = mail_find_command (argv[0]); - free (cmd); + /* Special case: a number alone implies "print" */ + if (argc == 1 + && ((strtoul (argv[0], &p, 10) > 0 && *p == 0) + || (argv[0][1] == 0 && strchr ("^$", argv[0][0])))) + { + /* Use the extra slot for "print" command */ + argc++; + argv--; + argv[0] = "print"; } + + entry = mail_find_command (argv[0]); + free (cmd); } - else - entry = mail_find_command (mailvar_name_quit); if (!entry) { @@ -221,7 +218,7 @@ util_range_msg (size_t low, size_t high, int flags, { msgset_t *set = msgset_make_1 (low); func (set, mesg, data); - free (set); + msgset_free (set); } /* Bail out if we receive an interrupt. */ if (ml_got_interrupt () != 0) @@ -484,15 +481,56 @@ util_folder_path (const char *name) return folder; } +int outfilename_mode; + char * -util_get_sender (int msgno, int strip) +util_outfilename (mu_address_t addr) { - mu_message_t msg = NULL; - mu_address_t addr = NULL; - char *buf = NULL, *p; + char *buf, *p; + int rc; + + if ((rc = mu_address_aget_email (addr, 1, &buf)) != 0) + { + mu_error (_("Cannot determine sender name: %s"), mu_strerror (rc)); + return NULL; + } - mu_mailbox_get_message (mbox, msgno, &msg); - addr = get_sender_address (msg); + switch (mailvar_is_true (mailvar_name_mailx) + ? outfilename_local : outfilename_mode) + { + case outfilename_local: + p = strchr (buf, '@'); + if (p) + *p = 0; + break; + + case outfilename_email: + break; + + case outfilename_domain: + p = strchr (buf, '@'); + if (p) + { + p++; + memmove (buf, p, strlen (p) + 1); + } + else + { + free (buf); + buf = mu_strdup ("localdomain"); + } + break; + } + return buf; +} + +char * +util_message_sender (mu_message_t msg, int strip) +{ + mu_address_t addr = get_sender_address (msg); + char *buf; + int rc; + if (!addr) { mu_envelope_t env = NULL; @@ -501,29 +539,36 @@ util_get_sender (int msgno, int strip) if (mu_envelope_sget_sender (env, &buffer) || mu_address_create (&addr, buffer)) { - mu_error (_("Cannot determine sender name (msg %d)"), msgno); + mu_error (_("Cannot determine sender name")); return NULL; } } - if (mu_address_aget_email (addr, 1, &buf) || !buf) + if (strip) { - mu_error (_("Cannot determine sender name (msg %d)"), msgno); - mu_address_destroy (&addr); - return NULL; + buf = util_outfilename (addr); } - - if (strip) + else if ((rc = mu_address_aget_printable (addr, &buf)) != 0) { - p = strchr (buf, '@'); - if (p) - *p = 0; + mu_error (_("Cannot determine sender name: %s"), mu_strerror (rc)); + buf = NULL; } - + mu_address_destroy (&addr); return buf; } +char * +util_get_sender (int msgno, int strip) +{ + mu_message_t msg; + if (mu_mailbox_get_message (mbox, msgno, &msg) == 0) + { + return util_message_sender (msg, strip); + } + return 0; +} + void util_slist_print (mu_list_t list, int nl) { @@ -646,47 +691,91 @@ util_strcat (char **dest, const char *str) char * util_outfolder_name (char *str) { + char *template = NULL; + char *folder; char *outfolder; - char *exp; int rc; if (!str) - return NULL; - - switch (*str) { - case '/': - case '~': - case '+': - rc = mu_mailbox_expand_name (str, &exp); - if (rc) + mailvar_get (&template, mailvar_name_record, mailvar_type_string, 0); + str = template; + } + else + { + switch (*str) { - mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_expand_name", str, rc); - return NULL; + case '/': + case '~': + case '+': + break; + + default: + if (mailvar_is_true (mailvar_name_mailx)) + { + if (mailvar_get (NULL, mailvar_name_outfolder, + mailvar_type_whatever, 0) == 0) + { + if (mailvar_get (&folder, mailvar_name_folder, + mailvar_type_string, 0) == 0) + template = mu_make_file_name (folder, str); + } + str = template; + } + else if (mailvar_get (&outfolder, mailvar_name_outfolder, + mailvar_type_string, 0) == 0) + { + str = template = mu_make_file_name (outfolder, str); + } + else if (mailvar_is_true (mailvar_name_outfolder)) + { + if (mailvar_get (&folder, mailvar_name_folder, + mailvar_type_string, 0) == 0) + template = mu_make_file_name (folder, str); + str = template; + } + else + str = NULL; + break; } - break; + } + + if (str) + { + char *tilde_template = NULL; + char *exp; - default: - if (mailvar_get (&outfolder, mailvar_name_outfolder, - mailvar_type_string, 0) == 0) + if (mailvar_is_true (mailvar_name_mailx)) { - char *s = mu_make_file_name (outfolder, str); - rc = mu_mailbox_expand_name (s, &exp); - if (rc) + switch (*str) { - mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_expand_name", s, rc); - free (s); - return NULL; + case '/': + case '~': + case '+': + break; + + default: + if (mu_asprintf (&tilde_template, "~/%s", str)) + { + mu_alloc_die (); + } + str = tilde_template; } - free (s); + } + + rc = mu_mailbox_expand_name (str, &exp); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_mailbox_expand_name", str, rc); + str = NULL; } else - exp = mu_strdup (str); - break; - + str = exp; + free (tilde_template); } - - return exp; + free (template); + + return str; } /* Save an outgoing message. The SAVEFILE argument overrides the setting @@ -694,38 +783,35 @@ util_outfolder_name (char *str) void util_save_outgoing (mu_message_t msg, char *savefile) { - char *record; - - if (mailvar_get (&record, mailvar_name_record, mailvar_type_string, 0) == 0) + char *filename = util_outfolder_name (savefile); + if (filename) { int rc; mu_mailbox_t outbox; - char *filename = util_outfolder_name (savefile ? savefile : record); rc = mu_mailbox_create_default (&outbox, filename); if (rc) { mu_error (_("Cannot create output mailbox `%s': %s"), - filename, mu_strerror (rc)); - free (filename); - return; - } - - rc = mu_mailbox_open (outbox, MU_STREAM_WRITE | MU_STREAM_CREAT); - if (rc) - mu_error (_("Cannot open output mailbox `%s': %s"), filename, mu_strerror (rc)); + } else { - rc = mu_mailbox_append_message (outbox, msg); + rc = mu_mailbox_open (outbox, MU_STREAM_WRITE | MU_STREAM_CREAT); if (rc) - mu_error (_("Cannot append message to `%s': %s"), - filename, mu_strerror (rc)); + mu_error (_("Cannot open output mailbox `%s': %s"), + filename, mu_strerror (rc)); + else + { + rc = mu_mailbox_append_message (outbox, msg); + if (rc) + mu_error (_("Cannot append message to `%s': %s"), + filename, mu_strerror (rc)); + } + + mu_mailbox_close (outbox); + mu_mailbox_destroy (&outbox); } - - mu_mailbox_close (outbox); - mu_mailbox_destroy (&outbox); - free (filename); } } @@ -886,13 +972,56 @@ is_address_field (const char *name) return 0; } +void +util_address_expand_aliases (mu_address_t *paddr) +{ + struct mu_address hint; + mu_address_t addr = *paddr; + mu_address_t new_addr = NULL; + int rc; + + memset (&hint, 0, sizeof (hint)); + while (addr) + { + struct mu_address *next = addr->next; + addr->next = NULL; + + if (addr->domain == NULL) + { + char *exp = alias_expand (addr->local_part); + if (exp) + { + mu_address_destroy (&addr); + rc = mu_address_create_hint (&addr, exp, &hint, 0); + if (rc) + { + mu_error (_("Cannot parse address `%s': %s"), + exp, mu_strerror (rc)); + free (exp); + continue; + } + free (exp); + } + } + mu_address_union (&new_addr, addr); + mu_address_destroy (&addr); + + addr = next; + } + *paddr = new_addr; +} + int -util_header_expand (mu_header_t *phdr) +util_header_expand_aliases (mu_header_t *phdr) { size_t i, nfields = 0; mu_header_t hdr; int errcnt = 0, rc; + if (mailvar_is_true (mailvar_name_inplacealiases)) + /* If inplacealiases was set, aliases have been already expanded */ + return 0; + rc = mu_header_create (&hdr, "", 0); if (rc) { @@ -903,84 +1032,54 @@ util_header_expand (mu_header_t *phdr) mu_header_get_field_count (*phdr, &nfields); for (i = 1; i <= nfields; i++) { - const char *name, *value; + const char *name; + char *value; if (mu_header_sget_field_name (*phdr, i, &name)) continue; - if (mu_header_sget_field_value (*phdr, i, &value)) + if (mu_header_aget_field_value (*phdr, i, &value)) continue; if (is_address_field (name)) { + struct mu_address hint; const char *s; - mu_address_t addr = NULL; - struct mu_wordsplit ws; - size_t j; - - if (mu_header_sget_value (hdr, name, &s) == 0) - mu_address_create (&addr, s); - - ws.ws_delim = ","; - if (mu_wordsplit (value, &ws, - MU_WRDSF_DELIM|MU_WRDSF_SQUEEZE_DELIMS| - MU_WRDSF_WS| - MU_WRDSF_NOVAR|MU_WRDSF_NOCMD)) + mu_address_t a = NULL; + + mu_string_unfold (value, NULL); + + memset (&hint, 0, sizeof (hint)); + rc = mu_address_create_hint (&a, value, &hint, 0); + if (rc == 0) { - errcnt++; - mu_error (_("cannot split line `%s': %s"), value, - mu_wordsplit_strerror (&ws)); + mu_address_t ha = NULL; + util_address_expand_aliases (&a); + if (mu_header_sget_value (hdr, name, &s) == 0) + mu_address_create_hint (&ha, s, &hint, 0); + mu_address_union (&ha, a); + mu_address_destroy (&a); + a = ha; } else { - for (j = 0; j < ws.ws_wordc; j++) - { - char *exp_mem = NULL; - mu_address_t new_addr; - char *p = ws.ws_wordv[j]; - char *exp; - - if (mailvar_is_true (mailvar_name_inplacealiases)) - /* If inplacealiases was set, the value was a - lready expanded */ - exp = p; - else - { - exp_mem = alias_expand (p); - exp = exp_mem ? exp_mem : p; - } - rc = mu_address_create (&new_addr, exp); - if (rc) - { - errcnt++; - if (exp_mem) - mu_error (_("Cannot parse address `%s'" - " (while expanding `%s'): %s"), - exp, p, mu_strerror (rc)); - else - mu_error (_("Cannot parse address `%s': %s"), - p, mu_strerror (rc)); - } - - mu_address_union (&addr, new_addr); - mu_address_destroy (&new_addr); - free (exp_mem); - } + mu_error (_("Cannot parse address `%s': %s"), + value, mu_strerror (rc)); + } - if (addr) - { - const char *newvalue; + if (a) + { + const char *newvalue; - rc = mu_address_sget_printable (addr, &newvalue); - if (rc == 0 && newvalue) - mu_header_set_value (hdr, name, newvalue, 1); - mu_address_destroy (&addr); - } + rc = mu_address_sget_printable (a, &newvalue); + if (rc == 0 && newvalue) + mu_header_set_value (hdr, name, newvalue, 1); + mu_address_destroy (&a); } - mu_wordsplit_free (&ws); } else mu_header_append (hdr, name, value); + free (value); } if (errcnt == 0) @@ -1119,12 +1218,12 @@ util_get_charset (void) { struct mu_lc_all lc_all = { .flags = 0 }; char *tmp = getenv ("LC_ALL"); - if (!tmp) + if (!tmp || !*tmp) tmp = getenv ("LANG"); if (tmp && mu_parse_lc_all (tmp, &lc_all, MU_LC_CSET) == 0) { - charset = mu_strdup (lc_all.charset); + charset = lc_all.charset ? mu_strdup (lc_all.charset) : NULL; mu_lc_all_free (&lc_all); } else @@ -1204,3 +1303,60 @@ open_pager (size_t lines) } return str; } + +int +util_get_folder (mu_folder_t *pfolder, mu_url_t url, int type) +{ + mu_folder_t folder; + int rc; + + rc = mu_folder_create_from_record (&folder, url, NULL); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_create", + mu_url_to_string (url), rc); + return -1; + } + + if (!mu_folder_is_local (folder)) + { + if (type == local_folder) + { + /* TRANSLATORS: The subject of this sentence ("folder") is the + name of the variable. Don't translate it. */ + mu_error ("%s", _("folder must be set to a local folder")); + mu_folder_destroy (&folder); + return -1; + } + + /* Set ticket for a remote folder */ + rc = mu_folder_attach_ticket (folder); + if (rc) + { + mu_authority_t auth = NULL; + + if (mu_folder_get_authority (folder, &auth) == 0 && auth) + { + mu_ticket_t tct; + mu_noauth_ticket_create (&tct); + rc = mu_authority_set_ticket (auth, tct); + if (rc) + mu_diag_funcall (MU_DIAG_ERROR, "mu_authority_set_ticket", + NULL, rc); + } + } + } + + rc = mu_folder_open (folder, MU_STREAM_READ); + if (rc) + { + mu_diag_funcall (MU_DIAG_ERROR, "mu_folder_open", + mu_url_to_string (url), rc); + mu_folder_destroy (&folder); + return -1; + } + + *pfolder = folder; + return 0; +} + |