From a27c8f1534294e302d28b38178152cf3b9a908fb Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Sun, 10 Mar 2019 13:27:11 +0800 Subject: [PATCH] Add mutt_buffer_expand_path() TODO: '@' expansion using mutt_default_save() is still using a fixed size string parameter. Convert imap_expand_path() and mutt_rx_sanitize_string() to use BUFFERS instead. Add url_ciss_tobuffer(). Co-authored-by: Richard Russon --- email/url.c | 53 +++++++++++++--------- email/url.h | 1 + imap/imap.c | 14 ++++++ imap/imap.h | 1 + mutt/file.c | 25 ++++------- mutt/file.h | 3 +- muttlib.c | 123 ++++++++++++++++++++++++++++++++-------------------- muttlib.h | 3 +- 8 files changed, 137 insertions(+), 86 deletions(-) diff --git a/email/url.c b/email/url.c index 12257bc16..dc543ac83 100644 --- a/email/url.c +++ b/email/url.c @@ -339,56 +339,67 @@ void url_pct_encode(char *buf, size_t buflen, const char *src) } /** - * url_tostring - Output the URL string for a given Url object + * url_tobuffer - Output the URL string for a given Url object * @param u Url to turn into a string * @param buf Buffer for the result - * @param buflen Length of buffer * @param flags Flags, e.g. #U_PATH * @retval 0 Success * @retval -1 Error */ -int url_tostring(struct Url *u, char *buf, size_t buflen, int flags) +int url_tobuffer(struct Url *u, struct Buffer *buf, int flags) { if (u->scheme == U_UNKNOWN) return -1; - snprintf(buf, buflen, "%s:", mutt_map_get_name(u->scheme, UrlMap)); + mutt_buffer_printf(buf, "%s:", mutt_map_get_name(u->scheme, UrlMap)); if (u->host) { if (!(flags & U_PATH)) - mutt_str_strcat(buf, buflen, "//"); - size_t l = strlen(buf); - buflen -= l; - buf += l; + mutt_buffer_addstr(buf, "//"); if (u->user && (u->user[0] || !(flags & U_PATH))) { char str[256]; url_pct_encode(str, sizeof(str), u->user); - snprintf(buf, buflen, "%s@", str); - l = strlen(buf); - buflen -= l; - buf += l; + mutt_buffer_add_printf(buf, "%s@", str); } if (strchr(u->host, ':')) - snprintf(buf, buflen, "[%s]", u->host); + mutt_buffer_add_printf(buf, "[%s]", u->host); else - snprintf(buf, buflen, "%s", u->host); - - l = strlen(buf); - buflen -= l; - buf += l; + mutt_buffer_add_printf(buf, "%s", u->host); if (u->port) - snprintf(buf, buflen, ":%hu/", u->port); + mutt_buffer_add_printf(buf, ":%hu/", u->port); else - snprintf(buf, buflen, "/"); + mutt_buffer_addstr(buf, "/"); } if (u->path) - mutt_str_strcat(buf, buflen, u->path); + mutt_buffer_addstr(buf, u->path); return 0; } + +/** + * url_tostring - Output the URL string for a given Url object + * @param u Url to turn into a string + * @param dest Buffer for the result + * @param len Length of buffer + * @param flags Flags, e.g. #U_PATH + * @retval 0 Success + * @retval -1 Error + */ +int url_tostring(struct Url *u, char *dest, size_t len, int flags) +{ + struct Buffer *dest_buf = mutt_buffer_pool_get(); + + int retval = url_tobuffer(u, dest_buf, flags); + if (retval == 0) + mutt_str_strfcpy(dest, mutt_b2s(dest_buf), len); + + mutt_buffer_pool_release(&dest_buf); + + return retval; +} diff --git a/email/url.h b/email/url.h index 40d122ddb..9d8b4de9d 100644 --- a/email/url.h +++ b/email/url.h @@ -81,6 +81,7 @@ void url_free(struct Url **u); struct Url *url_parse(const char *src); int url_pct_decode(char *s); void url_pct_encode(char *buf, size_t buflen, const char *src); +int url_tobuffer(struct Url *u, struct Buffer *dest, int flags); int url_tostring(struct Url *u, char *buf, size_t buflen, int flags); #endif /* MUTT_EMAIL_URL_H */ diff --git a/imap/imap.c b/imap/imap.c index d67100e1d..c9c97454e 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -2490,6 +2490,20 @@ int imap_path_canon(char *buf, size_t buflen) return 0; } +/** + * imap_expand_path - Buffer wrapper around imap_path_canon() + * @param buf Path to expand + * @retval 0 Success + * @retval -1 Failure + * + * @note The path is expanded in place + */ +int imap_expand_path(struct Buffer *buf) +{ + mutt_buffer_increase_size(buf, PATH_MAX); + return imap_path_canon(buf->data, PATH_MAX); +} + /** * imap_path_pretty - Implements MxOps::path_pretty() */ diff --git a/imap/imap.h b/imap/imap.h index fa55eb700..7bd45e0b7 100644 --- a/imap/imap.h +++ b/imap/imap.h @@ -105,6 +105,7 @@ int imap_copy_messages(struct Mailbox *m, struct EmailList *el, char *dest, bool void imap_logout_all(void); /* util.c */ +int imap_expand_path(struct Buffer *buf); int imap_parse_path(const char *path, struct ConnAccount *account, char *mailbox, size_t mailboxlen); void imap_pretty_mailbox(char *path, size_t pathlen, const char *folder); diff --git a/mutt/file.c b/mutt/file.c index e2fd5bae3..6b8a6224c 100644 --- a/mutt/file.c +++ b/mutt/file.c @@ -42,6 +42,7 @@ #include #include #include "file.h" +#include "buffer.h" #include "logging.h" #include "memory.h" #include "message.h" @@ -587,30 +588,22 @@ void mutt_file_sanitize_filename(char *fp, bool slash) /** * mutt_file_sanitize_regex - Escape any regex-magic characters in a string - * @param dest Buffer for result - * @param destlen Length of buffer - * @param src String to transform + * @param dest Buffer for result + * @param src String to transform * @retval 0 Success * @retval -1 Error */ -int mutt_file_sanitize_regex(char *dest, size_t destlen, const char *src) +int mutt_file_sanitize_regex(struct Buffer *dest, const char *src) { - while (*src && (--destlen > 2)) + mutt_buffer_reset(dest); + while (*src != '\0') { if (strchr(rx_special_chars, *src)) - { - *dest++ = '\\'; - destlen--; - } - *dest++ = *src++; + mutt_buffer_addch(dest, '\\'); + mutt_buffer_addch(dest, *src++); } - *dest = '\0'; - - if (*src) - return -1; - else - return 0; + return 0; } /** diff --git a/mutt/file.h b/mutt/file.h index 50ff76c21..09bf95e59 100644 --- a/mutt/file.h +++ b/mutt/file.h @@ -29,6 +29,7 @@ #include #include +struct Buffer; struct stat; extern char *C_Tmpdir; @@ -109,7 +110,7 @@ int mutt_file_rename(const char *oldfile, const char *newfile); int mutt_file_rmtree(const char *path); int mutt_file_safe_rename(const char *src, const char *target); void mutt_file_sanitize_filename(char *fp, bool slash); -int mutt_file_sanitize_regex(char *dest, size_t destlen, const char *src); +int mutt_file_sanitize_regex(struct Buffer *dest, const char *src); void mutt_file_set_mtime(const char *from, const char *to); int mutt_file_stat_compare(struct stat *sba, enum MuttStatType sba_type, struct stat *sbb, enum MuttStatType sbb_type); int mutt_file_stat_timespec_compare(struct stat *sba, enum MuttStatType type, struct timespec *b); diff --git a/muttlib.c b/muttlib.c index 7ed721088..5bc19dfaf 100644 --- a/muttlib.c +++ b/muttlib.c @@ -160,47 +160,47 @@ char *mutt_expand_path(char *buf, size_t buflen) } /** - * mutt_expand_path_regex - Create the canonical path (with regex char escaping) + * mutt_buffer_expand_path - Create the canonical path (with regex char escaping) * @param buf Buffer with path - * @param buflen Length of buffer * @param regex If true, escape any regex characters - * @retval ptr The expanded string * * @note The path is expanded in-place */ -char *mutt_expand_path_regex(char *buf, size_t buflen, bool regex) +void mutt_buffer_expand_path(struct Buffer *buf, bool regex) { - char p[PATH_MAX] = ""; - char q[PATH_MAX] = ""; - char tmp[PATH_MAX]; - + const char *s = NULL; const char *tail = ""; bool recurse = false; + struct Buffer *p = mutt_buffer_pool_get(); + struct Buffer *q = mutt_buffer_pool_get(); + struct Buffer *tmp = mutt_buffer_pool_get(); + do { recurse = false; + s = buf->data; - switch (*buf) + switch (*s) { case '~': { - if ((*(buf + 1) == '/') || (*(buf + 1) == 0)) + if ((*(s + 1) == '/') || (*(s + 1) == 0)) { - mutt_str_strfcpy(p, HomeDir, sizeof(p)); - tail = buf + 1; + mutt_buffer_strcpy(p, HomeDir); + tail = s + 1; } else { - char *t = strchr(buf + 1, '/'); + char *t = strchr(s + 1, '/'); if (t) *t = '\0'; - struct passwd *pw = getpwnam(buf + 1); + struct passwd *pw = getpwnam(s + 1); if (pw) { - mutt_str_strfcpy(p, pw->pw_dir, sizeof(p)); + mutt_buffer_strcpy(p, pw->pw_dir); if (t) { *t = '/'; @@ -214,8 +214,8 @@ char *mutt_expand_path_regex(char *buf, size_t buflen, bool regex) /* user not found! */ if (t) *t = '/'; - *p = '\0'; - tail = buf; + mutt_buffer_reset(p); + tail = s; } } break; @@ -230,16 +230,16 @@ char *mutt_expand_path_regex(char *buf, size_t buflen, bool regex) if ((mb_type == MUTT_IMAP) && ((C_Folder[strlen(C_Folder) - 1] == '}') || (C_Folder[strlen(C_Folder) - 1] == '/'))) { - mutt_str_strfcpy(p, C_Folder, sizeof(p)); + mutt_buffer_strcpy(p, NONULL(C_Folder)); } else if (mb_type == MUTT_NOTMUCH) - mutt_str_strfcpy(p, C_Folder, sizeof(p)); + mutt_buffer_strcpy(p, NONULL(C_Folder)); else if (C_Folder && *C_Folder && (C_Folder[strlen(C_Folder) - 1] == '/')) - mutt_str_strfcpy(p, C_Folder, sizeof(p)); + mutt_buffer_strcpy(p, NONULL(C_Folder)); else - snprintf(p, sizeof(p), "%s/", NONULL(C_Folder)); + mutt_buffer_printf(p, "%s/", NONULL(C_Folder)); - tail = buf + 1; + tail = s + 1; break; } @@ -247,19 +247,24 @@ char *mutt_expand_path_regex(char *buf, size_t buflen, bool regex) case '@': { - struct Address *alias = mutt_alias_lookup(buf + 1); + struct Address *alias = mutt_alias_lookup(s + 1); if (alias) { struct Email *e = mutt_email_new(); e->env = mutt_env_new(); e->env->from = alias; e->env->to = alias; - mutt_default_save(p, sizeof(p), e); + + /* TODO: fix mutt_default_save() to use Buffer */ + mutt_buffer_increase_size(p, PATH_MAX); + mutt_default_save(p->data, p->dsize, e); + mutt_buffer_fix_dptr(p); + e->env->from = NULL; e->env->to = NULL; mutt_email_free(&e); /* Avoid infinite recursion if the resulting folder starts with '@' */ - if (*p != '@') + if (*(p->data) != '@') recurse = true; tail = ""; @@ -269,71 +274,95 @@ char *mutt_expand_path_regex(char *buf, size_t buflen, bool regex) case '>': { - mutt_str_strfcpy(p, C_Mbox, sizeof(p)); - tail = buf + 1; + mutt_buffer_strcpy(p, C_Mbox); + tail = s + 1; break; } case '<': { - mutt_str_strfcpy(p, C_Record, sizeof(p)); - tail = buf + 1; + mutt_buffer_strcpy(p, C_Record); + tail = s + 1; break; } case '!': { - if (*(buf + 1) == '!') + if (*(s + 1) == '!') { - mutt_str_strfcpy(p, LastFolder, sizeof(p)); - tail = buf + 2; + mutt_buffer_strcpy(p, LastFolder); + tail = s + 2; } else { - mutt_str_strfcpy(p, C_Spoolfile, sizeof(p)); - tail = buf + 1; + mutt_buffer_strcpy(p, C_Spoolfile); + tail = s + 1; } break; } case '-': { - mutt_str_strfcpy(p, LastFolder, sizeof(p)); - tail = buf + 1; + mutt_buffer_strcpy(p, LastFolder); + tail = s + 1; break; } case '^': { - mutt_str_strfcpy(p, CurrentFolder, sizeof(p)); - tail = buf + 1; + mutt_buffer_strcpy(p, CurrentFolder); + tail = s + 1; break; } default: { - *p = '\0'; - tail = buf; + mutt_buffer_reset(p); + tail = s; } } - if (regex && *p && !recurse) + if (regex && *p->data && !recurse) { - mutt_file_sanitize_regex(q, sizeof(q), p); - snprintf(tmp, sizeof(tmp), "%s%s", q, tail); + mutt_file_sanitize_regex(q, mutt_b2s(p)); + mutt_buffer_printf(tmp, "%s%s", mutt_b2s(q), tail); } else - snprintf(tmp, sizeof(tmp), "%s%s", p, tail); + mutt_buffer_printf(tmp, "%s%s", mutt_b2s(p), tail); - mutt_str_strfcpy(buf, tmp, buflen); + mutt_buffer_strcpy(buf, mutt_b2s(tmp)); } while (recurse); + mutt_buffer_pool_release(&p); + mutt_buffer_pool_release(&q); + mutt_buffer_pool_release(&tmp); + #ifdef USE_IMAP /* Rewrite IMAP path in canonical form - aids in string comparisons of * folders. May possibly fail, in which case buf should be the same. */ - if (imap_path_probe(buf, NULL) == MUTT_IMAP) - imap_path_canon(buf, buflen); + if (imap_path_probe(mutt_b2s(buf), NULL) == MUTT_IMAP) + imap_expand_path(buf); #endif +} + +/** + * mutt_expand_path_regex - Create the canonical path (with regex char escaping) + * @param buf Buffer with path + * @param buflen Length of buffer + * @param regex If true, escape any regex characters + * @retval ptr The expanded string + * + * @note The path is expanded in-place + */ +char *mutt_expand_path_regex(char *buf, size_t buflen, bool regex) +{ + struct Buffer *tmp = mutt_buffer_pool_get(); + + mutt_buffer_addstr(tmp, buf); + mutt_buffer_expand_path(tmp, regex); + mutt_str_strfcpy(buf, mutt_b2s(tmp), buflen); + + mutt_buffer_pool_release(&tmp); return buf; } diff --git a/muttlib.h b/muttlib.h index e062330fc..67b2d9abe 100644 --- a/muttlib.h +++ b/muttlib.h @@ -45,11 +45,12 @@ extern struct Regex *C_GecosMask; void mutt_adv_mktemp(char *s, size_t l); void mutt_buffer_adv_mktemp (struct Buffer *buf); void mutt_buffer_mktemp_full(struct Buffer *buf, const char *prefix, const char *suffix, const char *src, int line); +void mutt_buffer_expand_path(struct Buffer *buf, bool regex); int mutt_check_overwrite(const char *attname, const char *path, char *fname, size_t flen, enum SaveAttach *opt, char **directory); void mutt_encode_path(char *dest, size_t dlen, const char *src); void mutt_expando_format(char *buf, size_t buflen, size_t col, int cols, const char *src, format_t *callback, unsigned long data, MuttFormatFlags flags); char * mutt_expand_path(char *s, size_t slen); -char * mutt_expand_path_regex(char *s, size_t slen, bool regex); +char * mutt_expand_path_regex(char *buf, size_t buflen, bool regex); char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw); void mutt_get_parent_path(char *path, char *buf, size_t buflen); int mutt_inbox_cmp(const char *a, const char *b); -- 2.40.0