85 if (!(buf->
data && (buf->
data[0] !=
'\0')))
97 struct stat st = { 0 };
101 char *suffix = strchr(prefix->
data,
'.');
136 const char *s = NULL;
137 const char *tail =
"";
139 bool recurse =
false;
154 if ((s[1] ==
'/') || (s[1] ==
'\0'))
161 char *t = strchr(s + 1,
'/');
165 struct passwd *pw = getpwnam(s + 1);
198 if ((mb_type ==
MUTT_IMAP) && ((c_folder[strlen(c_folder) - 1] ==
'}') ||
199 (c_folder[strlen(c_folder) - 1] ==
'/')))
205 else if (c_folder && (c_folder[strlen(c_folder) - 1] ==
'/'))
366 regmatch_t pat_match[1];
370 if (!pw || !pw->pw_gecos)
373 memset(dest, 0, destlen);
379 MIN(pat_match[0].rm_eo - pat_match[0].rm_so + 1, destlen));
381 else if ((p = strchr(pw->pw_gecos,
',')))
386 pwnl = strlen(pw->pw_name);
388 for (
int idx = 0; dest[idx]; idx++)
390 if (dest[idx] ==
'&')
392 memmove(&dest[idx + pwnl], &dest[idx + 1],
393 MAX((ssize_t) (destlen - idx - pwnl - 1), 0));
394 memcpy(&dest[idx], pw->pw_name,
MIN(destlen - idx - 1, pwnl));
395 dest[idx] = toupper((
unsigned char) dest[idx]);
474 char *p = buf, *q = buf;
494 p = strchr(buf,
':') + 1;
496 q = strchr(p + 2,
'/');
503 if (strstr(p,
"//") || strstr(p,
"/./"))
509 if ((p[0] ==
'/') && (p[1] ==
'/'))
514 else if ((p[0] ==
'/') && (p[1] ==
'.') && (p[2] ==
'/'))
524 else if (strstr(p,
"..") && ((scheme ==
U_UNKNOWN) || (scheme ==
U_FILE)) &&
538 memmove(buf, buf + len - 1,
mutt_str_len(buf + len - 1) + 1);
548 if (!buf || !buf->
data)
571 struct stat st = { 0 };
578 if (S_ISDIR(st.st_mode))
587 (
_(
"File is a directory, save under it: (y)es, (n)o, (a)ll?"),
_(
"yna")))
606 return (ans ==
MUTT_NO) ? 1 : -1;
611 false, NULL, NULL, NULL) != 0) ||
623 char buf[4096] = { 0 };
626 _(
"File exists, (o)verwrite, (a)ppend, or (c)ancel?"));
662 char *p = strpbrk(buf,
"%@");
685 char *p = strpbrk(dest->
data,
"%@");
710 for (
char *p = dest->
data; *p; p++)
729 char prefix[128], tmp[1024];
730 char *cp = NULL, *wptr = buf;
732 char if_str[128], else_str[128];
733 size_t wlen, count, len, wid;
734 FILE *fp_filter = NULL;
735 char *recycler = NULL;
757 if ((n > 1) && (src[n - 1] ==
'|'))
761 while ((off > 0) && (src[off - 2] ==
'\\'))
767 if ((off > 0) && (((n - off) % 2) == 0))
769 char srccopy[1024] = { 0 };
774 strncpy(srccopy, src, n);
775 srccopy[n - 1] =
'\0';
798 for (
char *p = tmp; p && (*p !=
'\0'); p++)
826 n = fread(buf, 1, buflen , fp_filter);
834 while ((n > 0) && ((buf[n - 1] ==
'\n') || (buf[n - 1] ==
'\r')))
842 if ((n > 0) && (buf[n - 1] ==
'%'))
846 if ((n > 0) && (buf[n - 1] !=
'%'))
856 callback,
data, flags);
866 strerror(errno), errno);
883 while (*src && (wlen < buflen))
900 char *p = (
char *) src;
903 for (; *p && (*p !=
'?'); p++)
910 for (; *p && (*p !=
'?'); p++)
913 if ((*p ==
'<') || (*p ==
'>'))
931 while ((count < (
sizeof(prefix) - 1)) && (*src !=
'\0') && (*src !=
'?'))
940 flags &= ~MUTT_FORMAT_OPTIONAL;
945 while ((count < (
sizeof(prefix) - 1)) && strchr(
"0123456789.-=", *src))
970 while ((lrbalance > 0) && (count <
sizeof(if_str)) && *src)
972 if ((src[0] ==
'%') && (src[1] ==
'>'))
986 else if ((src[0] ==
'%') && (src[1] ==
'<'))
990 else if (src[0] ==
'>')
996 if ((lrbalance == 1) && (src[0] ==
'&'))
1008 while ((lrbalance > 0) && (count <
sizeof(else_str)) && (*src !=
'\0'))
1010 if ((src[0] ==
'%') && (src[1] ==
'>'))
1024 else if ((src[0] ==
'%') && (src[1] ==
'<'))
1028 else if (src[0] ==
'>')
1034 if ((lrbalance == 1) && (src[0] ==
'&'))
1048 if ((ch ==
'>') || (ch ==
'*'))
1052 int soft = ch ==
'*';
1062 if (((col < cols) && (wlen < buflen)) || soft)
1071 pad = (cols - col - wid) / pw;
1076 if (wlen + (
pad * pl) + len > buflen)
1078 pad = (buflen > (wlen + len)) ? ((buflen - wlen - len) / pl) : 0;
1084 while (((col + (
pad * pw) + wid) < cols) && ((wlen + (
pad * pl) + len) < buflen))
1093 memcpy(wptr, src, pl);
1104 int avail_cols = (cols > offset) ? (cols - offset) : 0;
1114 while (((col + wid) < avail_cols) && ((wlen + len) < buflen))
1121 if ((len + wlen) > buflen)
1123 memcpy(wptr, tmp, len);
1140 if ((col < cols) && (wlen < buflen))
1142 int c = (cols - col) / pw;
1143 if ((c > 0) && ((wlen + (c * pl)) > buflen))
1144 c = ((signed) (buflen - wlen)) / pl;
1147 memcpy(wptr, src, pl);
1158 bool to_lower =
false;
1159 bool no_dots =
false;
1161 while ((ch ==
'_') || (ch ==
':'))
1173 src = callback(tmp,
sizeof(tmp), col, cols, ch, src, prefix, if_str,
1174 else_str,
data, flags);
1187 if ((len + wlen) > buflen)
1190 memcpy(wptr, tmp, len);
1196 else if (*src ==
'\\')
1236 if ((bytes > 0) && ((wlen + bytes) < buflen))
1238 memcpy(wptr, src, bytes);
1246 src += buflen - wlen;
1267 struct stat st = { 0 };
1275 if (path[len - 1] ==
'|')
1288 if (stat(path, &st) < 0)
1290 if (S_ISDIR(st.st_mode))
1295 fp = fopen(path,
"r");
1318 mutt_error(
_(
"Can't save message to POP mailbox"));
1326 if (c_confirm_append)
1342 mutt_error(
_(
"Can't save message to news server"));
1347 if (stat(s, st) != -1)
1361 if (errno == ENOENT)
1364 if (c_confirm_create)
1411 if (c_sleep_time > s)
1412 sleep(c_sleep_time);
1425 static char vstring[256];
1426 snprintf(vstring,
sizeof(vstring),
"NeoMutt %s%s", PACKAGE_VERSION,
GitVer);
1445 for (
size_t i = 0; i < len; i++)
1447 if (!isalnum(buf->
data[i]) && !strchr(
"/.-_", buf->
data[i]))
1519 if (buf[n - 1] ==
'/')
1523 for (n--; ((n >= 0) && (buf[n] !=
'/')); n--)
1563 if ((a[0] ==
'+') && (b[0] ==
'+'))
1570 const char *a_end = strrchr(a,
'/');
1571 const char *b_end = strrchr(b,
'/');
1574 if ((!a_end) ^ (!b_end))
1582 size_t a_len = a_end - a;
1583 size_t b_len = b_end - b;
1584 size_t min =
MIN(a_len, b_len);
1585 int same = (a[min] ==
'/') && (b[min] ==
'/') && (a[min + 1] !=
'\0') &&
1613 for (; *path; path++)
1630 if (!buf || (buflen == 0))
1638 if (c_size_show_bytes && (num < 1024))
1640 snprintf(buf, buflen,
"%d", (
int) num);
1644 mutt_str_copy(buf, c_size_units_on_left ?
"K0" :
"0K", buflen);
1646 else if (c_size_show_fractions && (num < 10189))
1648 snprintf(buf, buflen, c_size_units_on_left ?
"K%3.1f" :
"%3.1fK",
1649 (num < 103) ? 0.1 : (num / 1024.0));
1651 else if (!c_size_show_mb || (num < 1023949))
1654 snprintf(buf, buflen, c_size_units_on_left ? (
"K%zu") : (
"%zuK"), (num + 51) / 1024);
1656 else if (c_size_show_fractions && (num < 10433332))
1658 snprintf(buf, buflen, c_size_units_on_left ?
"M%3.1f" :
"%3.1fM", num / 1048576.0);
1663 snprintf(buf, buflen, c_size_units_on_left ? (
"M%zu") : (
"%zuM"), (num + 52428) / 1048576);
1677 if (!str || (*str ==
'\0'))
1707 struct ListNode *np = NULL, *tmp = NULL;
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
struct AddressList * alias_lookup(const char *name)
Find an Alias.
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
void mutt_buffer_seek(struct Buffer *buf, size_t offset)
Set current read/write position to offset from beginning.
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Convenience wrapper for the config headers.
char * HomeDir
User's home directory.
Convenience wrapper for the core headers.
SecurityFlags mutt_is_application_pgp(struct Body *b)
Does the message use PGP?
SecurityFlags mutt_is_application_smime(struct Body *b)
Does the message use S/MIME?
size_t mutt_wstr_trunc(const char *src, size_t maxlen, size_t maxwid, size_t *width)
Work out how to truncate a widechar string.
void mutt_endwin(void)
Shutdown curses.
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
struct Email * email_new(void)
Create a new Email.
void email_free(struct Email **ptr)
Free an Email.
Structs that make up an email.
int mutt_buffer_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
struct Envelope * mutt_env_new(void)
Create a new Envelope.
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
int mutt_file_sanitize_regex(struct Buffer *dest, const char *src)
Escape any regex-magic characters in a string.
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
const char filename_safe_chars[]
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
char * LastFolder
Previously selected mailbox.
char * CurrentFolder
Currently selected mailbox.
void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t callback, intptr_t data, MuttFormatFlags flags)
Expand expandos (x) in a string -.
#define mutt_debug(LEVEL,...)
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Convenience wrapper for the gui headers.
static int pad(FILE *fp, int col, int i)
Write some padding to a file.
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Parse and execute user-defined hooks.
void imap_get_parent_path(const char *path, char *buf, size_t buflen)
Get the path of the parent folder.
void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder)
Prettify an IMAP mailbox name.
int imap_expand_path(struct Buffer *buf)
Buffer wrapper around imap_path_canon()
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
@ LL_DEBUG3
Log at debug level 3.
@ LL_DEBUG5
Log at debug level 5.
@ LL_DEBUG1
Log at debug level 1.
MailboxType
Supported mailbox formats.
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
@ MUTT_MAILBOX_ERROR
Error occurred examining Mailbox.
@ MUTT_POP
'POP3' Mailbox type
@ MUTT_NNTP
'NNTP' (Usenet) Mailbox type
@ MUTT_IMAP
'IMAP' Mailbox type
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
int mutt_mb_charlen(const char *s, int *width)
Count the bytes in a (multibyte) character.
@ TYPE_MESSAGE
Type: 'message/*'.
@ TYPE_MULTIPART
Type: 'multipart/*'.
@ TYPE_APPLICATION
Type: 'application/*'.
@ TYPE_TEXT
Type: 'text/*'.
void msgwin_clear_text(void)
Clear the text in the Message Window.
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Convenience wrapper for the library headers.
const char * mutt_path_basename(const char *f)
Find the last component for a pathname.
char * mutt_path_dirname(const char *path)
Return a path up to, but not including, the final '/'.
bool mutt_regex_capture(const struct Regex *regex, const char *str, size_t nmatch, regmatch_t matches[])
Match a regex against a string, with provided options.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
char * mutt_str_dup(const char *str)
Copy a string, safely.
char * mutt_str_lower(char *str)
Convert all characters in the string to lowercase.
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
bool mutt_strn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings (to a maximum), safely.
const char * mutt_str_getenv(const char *name)
Get an environment variable.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
bool mutt_istrn_equal(const char *a, const char *b, size_t num)
Check for equality of two strings ignoring case (to a maximum), safely.
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
char * mutt_str_sep(char **stringp, const char *delim)
Find first occurrence of any of delim characters in *stringp.
Many unsorted constants and some structs.
#define MUTT_COMP_FILE
File completion (in browser)
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
SaveAttach
Options for saving attachments.
@ MUTT_SAVE_APPEND
Append to existing file.
@ MUTT_SAVE_OVERWRITE
Overwrite existing file.
@ MUTT_SAVE_NO_FLAGS
No flags set.
char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex)
Create the canonical path (with regex char escaping)
void mutt_get_parent_path(const char *path, char *buf, size_t buflen)
Find the parent of a path (or mailbox)
void remove_from_stailq(struct ListHead *head, const char *str)
Remove an item, matching a string, from a List.
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
void add_to_stailq(struct ListHead *head, const char *str)
Add a string to a list.
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
int mutt_inbox_cmp(const char *a, const char *b)
Do two folders share the same path and one is an inbox.
const char * mutt_make_version(void)
Generate the NeoMutt version string.
void mutt_sleep(short s)
Sleep for a while.
void mutt_save_path(char *buf, size_t buflen, const struct Address *addr)
Turn an email address into a filename (for saving)
void mutt_buffer_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
static const char * xdg_env_vars[]
int mutt_set_xdg_path(enum XdgType type, struct Buffer *buf)
Find an XDG path or its fallback.
void mutt_str_pretty_size(char *buf, size_t buflen, size_t num)
Display an abbreviated size, like 3.4K.
bool mutt_is_text_part(struct Body *b)
Is this part of an email in plain text?
void mutt_pretty_mailbox(char *buf, size_t buflen)
Shorten a mailbox path using '~' or '='.
static const char * xdg_defaults[]
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
void mutt_safe_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
int mutt_check_overwrite(const char *attname, const char *path, struct Buffer *fname, enum SaveAttach *opt, char **directory)
Ask the user if overwriting is necessary.
void mutt_buffer_sanitize_filename(struct Buffer *buf, const char *path, short slash)
Replace unsafe characters in a filename.
void mutt_encode_path(struct Buffer *buf, const char *src)
Convert a path to 'us-ascii'.
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
FILE * mutt_open_read(const char *path, pid_t *thepid)
Run a command to read from.
Some miscellaneous functions.
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
enum MailboxType mx_path_probe(const char *path)
Find a mailbox that understands a path.
API for encryption/signing of emails.
#define APPLICATION_PGP
Use PGP to encrypt/sign.
#define APPLICATION_SMIME
Use SMIME to encrypt/sign.
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Prototypes for many functions.
XdgType
XDG variable types.
@ XDG_CONFIG_HOME
XDG home dir: ~/.config.
@ XDG_CONFIG_DIRS
XDG system dir: /etc/xdg.
QuadOption
Possible values for a quad-option.
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
@ MUTT_NO
User answered 'No', or assume 'No'.
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
#define STAILQ_REMOVE(head, elm, type, field)
#define STAILQ_FOREACH(var, head, field)
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
#define TAILQ_EMPTY(head)
char * mailbox
Mailbox and host address.
char * subtype
content-type subtype
unsigned int type
content-type primary type, ContentType
String manipulation buffer.
char * dptr
Current read/write position.
size_t dsize
Length of data.
char * data
Pointer to data.
The envelope/body of an email.
struct Envelope * env
Envelope information.
struct AddressList to
Email's 'To' list.
struct AddressList from
Email's 'From' list.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.
Cached regular expression.
#define mutt_buffer_mktemp_pfx_sfx(buf, prefix, suffix)
#define mutt_buffer_mktemp(buf)
enum UrlScheme url_check_scheme(const char *str)
Check the protocol of a URL.
UrlScheme
All recognised Url types.
@ U_NOTMUCH
Url is notmuch://.
@ U_UNKNOWN
Url wasn't recognised.
@ U_IMAPS
Url is imaps://.