summaryrefslogtreecommitdiff
path: root/mail/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'mail/util.c')
-rw-r--r--mail/util.c500
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;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.