flags.c filter.c from.c handler.c hcache.c hdrline.c headers.c help.c hook.c \
main.c mbox.c mh.c muttlib.c mutt_idna.c mx.c \
pager.c pattern.c postpone.c query.c \
- recvattach.c recvcmd.c rfc1524.c rfc3676.c \
+ recvattach.c recvcmd.c rfc3676.c \
score.c send.c sendlib.c sidebar.c sort.c state.c status.c \
thread.c account.c
dotlock.h functions.def gen_defs \
recvattach.h handler.h thread.h \
globals.h init.h keymap.h mutt_crypt.h \
- mime.h mutt.h mutt_sasl.h mbox.h mh.h mx.h pager.h protos.h rfc1524.h \
+ mime.h mutt.h mutt_sasl.h mbox.h mh.h mx.h pager.h protos.h \
rfc3676.h sort.h mime.types autogen.sh \
OPS.MIX remailer.c remailer.h browser.h state.h \
lib.h extlib.c pgpewrap.c smime_keys.pl pgplib.h madmuttrc.head madmuttrc \
#include "handler.h"
#include "recvattach.h"
#include "keymap.h"
-#include "rfc1524.h"
#include "pager.h"
#include "copy.h"
#include "mx.h"
{
char type[STRING];
char tempfile[_POSIX_PATH_MAX];
- rfc1524_entry *entry = rfc1524_new_entry ();
+ rfc1524_entry *entry = rfc1524_entry_new();
FILE *fpin = NULL, *fpout = NULL;
struct stat st;
rfc1524_expand_filename (entry->nametemplate, a->filename,
tempfile, sizeof (tempfile));
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
if (stat (a->filename, &st) == -1)
return -1;
char type[STRING];
char command[STRING];
char newfile[_POSIX_PATH_MAX] = "";
- rfc1524_entry *entry = rfc1524_new_entry ();
+ rfc1524_entry *entry = rfc1524_entry_new();
short unlink_newfile = 0;
int rc = 0;
}
}
else {
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
mutt_message (_("No mailcap compose entry for %s, creating empty file."),
type);
return 1;
if (unlink_newfile)
unlink (newfile);
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
return rc;
}
char type[STRING];
char command[STRING];
char newfile[_POSIX_PATH_MAX] = "";
- rfc1524_entry *entry = rfc1524_new_entry ();
+ rfc1524_entry *entry = rfc1524_entry_new();
short unlink_newfile = 0;
int rc = 0;
mutt_edit_file (NONULL (Editor), a->filename);
}
else {
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
mutt_error (_("No mailcap edit entry for %s"), type);
return 0;
}
if (unlink_newfile)
unlink (newfile);
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
return rc;
}
snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype);
if (use_mailcap) {
- entry = rfc1524_new_entry ();
+ entry = rfc1524_entry_new();
if (!rfc1524_mailcap_lookup (a, type, entry, 0)) {
if (flag == M_REGULAR) {
/* fallback to view as text */
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
mutt_error _("No matching mailcap entry found. Viewing as text.");
flag = M_AS_TEXT;
return_error:
if (entry)
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
if (fp && tempfile[0])
mutt_unlink (tempfile);
else if (unlink_tempfile)
rfc1524_entry *entry;
int piped = FALSE;
- entry = rfc1524_new_entry ();
+ entry = rfc1524_entry_new();
rfc1524_mailcap_lookup (a, type, entry, M_PRINT);
if (rfc1524_expand_filename (entry->nametemplate, a->filename,
newfile, sizeof (newfile))) {
if (safe_symlink (a->filename, newfile) == -1) {
if (mutt_yesorno (_("Can't match nametemplate, continue?"), M_YES)
!= M_YES) {
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
return 0;
}
m_strcpy(newfile, sizeof(newfile), a->filename);
if (piped) {
if ((ifp = fopen (newfile, "r")) == NULL) {
mutt_perror ("fopen");
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
return (0);
}
if ((thepid = mutt_create_filter (command, &fpout, NULL, NULL)) < 0) {
mutt_perror (_("Can't create filter"));
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
safe_fclose (&ifp);
return 0;
}
else if (unlink_newfile)
unlink (newfile);
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
return (1);
}
#include "pager.h"
#include <lib-crypt/crypt.h>
#include "mutt_idna.h"
-#include "rfc1524.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "mutt.h"
#include "alias.h"
#include "mutt_idna.h"
-#include "rfc1524.h"
#include "attach.h"
#include "recvattach.h"
#include "sort.h"
#include "mutt.h"
#include "recvattach.h"
#include "handler.h"
-#include "rfc1524.h"
#include "rfc3676.h"
#include "keymap.h"
#include "copy.h"
while (b) {
snprintf (buf, sizeof (buf), "%s/%s", TYPE (b), b->subtype);
if (mutt_is_autoview (b, buf)) {
- rfc1524_entry *entry = rfc1524_new_entry ();
+ rfc1524_entry *entry = rfc1524_entry_new();
if (rfc1524_mailcap_lookup (b, buf, entry, M_AUTOVIEW)) {
choice = b;
}
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
}
b = b->next;
}
static int autoview_handler (BODY * a, STATE * s)
{
- rfc1524_entry *entry = rfc1524_new_entry ();
+ rfc1524_entry *entry = rfc1524_entry_new();
char buffer[LONG_STRING];
char type[STRING];
char command[LONG_STRING];
if ((fpin = safe_fopen (tempfile, "w+")) == NULL) {
mutt_perror ("fopen");
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
return (-1);
}
if (s->flags & M_DISPLAY)
mutt_clear_error ();
}
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
return (rc);
}
snprintf (type, sizeof (type), "%s/%s", TYPE (b), b->subtype);
if (mutt_is_autoview (b, type)) {
- rfc1524_entry *entry = rfc1524_new_entry ();
+ rfc1524_entry *entry = rfc1524_entry_new();
if (rfc1524_mailcap_lookup (b, type, entry, M_AUTOVIEW)) {
handler = autoview_handler;
s->flags &= ~M_CHARCONV;
}
- rfc1524_free_entry (&entry);
+ rfc1524_entry_delete(&entry);
}
else if (b->type == TYPETEXT) {
if (ascii_strcasecmp ("plain", b->subtype) == 0) {
return r;
}
+/* If rfc1524_expand_command() is used on a recv'd message, then
+ * the filename doesn't exist yet, but if its used while sending a message,
+ * then we need to rename the existing file.
+ *
+ * This function returns 0 on successful move, 1 on old file doesn't exist,
+ * 2 on new file already exists, and 3 on other failure.
+ */
+
+/* note on access(2) use: No dangling symlink problems here due to
+ * safe_fopen().
+ */
+int mutt_rename_file(char *oldfile, char *newfile)
+{
+ FILE *ofp, *nfp;
+
+ if (access(oldfile, F_OK) != 0)
+ return 1;
+ if (access(newfile, F_OK) == 0)
+ return 2;
+
+ ofp = fopen(oldfile, "r");
+ if (!ofp)
+ return 3;
+
+ nfp = safe_fopen(newfile, "w");
+ if (!nfp) {
+ fclose (ofp);
+ return 3;
+ }
+
+ mutt_copy_stream(ofp, nfp);
+ fclose(nfp);
+ fclose(ofp);
+ mutt_unlink(oldfile);
+ return 0;
+}
+
/* Read a line from ``fp'' into the dynamically allocated ``s'',
* increasing ``s'' if necessary. The ending "\n" or "\r\n" is removed.
* If a line ends with "\", this char and the linefeed is removed,
/****************************************************************************/
FILE *safe_fopen(const char *, const char *);
+int mutt_rename_file(char *, char *);
int safe_fclose(FILE **);
char *mutt_read_line(char *, ssize_t *, FILE *, int *);
BUILT_SOURCES = mime-token.h mime-token.c
-CLEANFILES = $(BUILT_SOURCES)
+DISTCLEANFILES = $(BUILT_SOURCES)
noinst_LIBRARIES = libmime.a
libmime_a_SOURCES = mime.h mime-types.h $(BUILT_SOURCES) \
- mime.c rfc822address.c rfc822parse.c rfc2047.c rfc2231.c
+ mime.c rfc822address.c rfc822parse.c rfc1524.c rfc2047.c rfc2231.c
noinst_HEADERS = mime.h mime-types.h
bcc
binary
cc
+compose
+composetyped
content-description
content-disposition
content-length
content-transfer-encoding
content-type
+copiousoutput
date
digest
+edit
expires
external-body
followup-to
from
image
in-reply-to
-news
-rfc822
iso-2022-jp
lines
list-post
mime-version
model
multipart
+nametemplate
+needsterminal
+news
newsgroups
organization
+print
quoted-printable
received
references
reply-to
return-path
+rfc822
sender
status
subject
supercedes
supersedes
+test
text
to
unknown
utf-8
video
x-comment-to
+x-convert
x-label
xref
x-status
"x-uuencoded",
};
+void rfc1524_entry_wipe(rfc1524_entry *p)
+{
+ p_delete(&p->command);
+ p_delete(&p->testcommand);
+ p_delete(&p->composecommand);
+ p_delete(&p->composetypecommand);
+ p_delete(&p->editcommand);
+ p_delete(&p->printcommand);
+ p_delete(&p->nametemplate);
+ p_delete(&p->convert);
+}
+
void envelope_wipe(ENVELOPE *p)
{
address_list_wipe(&p->return_path);
*
* Copyright © 2006 Pierre Habouzit
*/
-
/*
* Copyright notice from original mutt:
* Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
int url_parse_mailto(ENVELOPE *e, char **body, const char *src);
+/****************************************************************************/
+/* RFC 1524 */
+/* A User Agent Configuration Mechanism */
+/* For Multimedia Mail Format Information */
+/****************************************************************************/
+
+typedef struct rfc1524_entry {
+ /* char *contenttype; *//* we don't need this, as we search for it */
+ char *command;
+ char *testcommand;
+ char *composecommand;
+ char *composetypecommand;
+ char *editcommand;
+ char *printcommand;
+ char *nametemplate;
+ char *convert;
+
+ unsigned needsterminal:1; /* endwin() and system */
+ unsigned copiousoutput:1; /* needs pager, basically */
+} rfc1524_entry;
+
+DO_INIT(rfc1524_entry, rfc1524_entry);
+void rfc1524_entry_wipe(rfc1524_entry *);
+
+DO_NEW(rfc1524_entry, rfc1524_entry);
+DO_DELETE(rfc1524_entry, rfc1524_entry);
+
+int rfc1524_expand_command(BODY *, const char *, const char *, char *, int);
+int rfc1524_expand_filename(char *, char *, char *, ssize_t);
+int rfc1524_mailcap_lookup (BODY *, char *, rfc1524_entry *, int);
+
/****************************************************************************/
/* RFC 822 */
/* Standard for ARPA Internet Text Messages */
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Copyright © 2006 Pierre Habouzit
+ */
+/*
+ * Copyright notice from original mutt:
+ * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
+ *
+ * This file is part of mutt-ng, see http://www.muttng.org/.
+ * It's licensed under the GNU General Public License,
+ * please see the file GPL in the top level source directory.
+ */
+
+/*
+ * rfc1524 defines a format for the Multimedia Mail Configuration, which
+ * is the standard mailcap file format under Unix which specifies what
+ * external programs should be used to view/compose/edit multimedia files
+ * based on content type.
+ *
+ * This file contains various functions for implementing a fair subset of
+ * rfc1524.
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+#include <lib-lib/ascii.h>
+#include <lib-lib/macros.h>
+#include <lib-lib/file.h>
+
+#include <lib-sys/unix.h>
+
+#include "mutt.h"
+#include "mime.h"
+#include "attach.h"
+
+/* The command semantics include the following:
+ * %s is the filename that contains the mail body data
+ * %t is the content type, like text/plain
+ * %{parameter} is replaced by the parameter value from the content-type field
+ * \% is %
+ * Unsupported rfc1524 parameters: these would probably require some doing
+ * by mutt, and can probably just be done by piping the message to metamail
+ * %n is the integer number of sub-parts in the multipart
+ * %F is "content-type filename" repeated for each sub-part
+ *
+ * In addition, this function returns a 0 if the command works on a file,
+ * and 1 if the command works on a pipe.
+ */
+int rfc1524_expand_command(BODY *a, const char *filename, const char *mtype,
+ char *command, int clen)
+{
+ int x = 0, y = 0;
+ int needspipe = TRUE;
+ char buf[LONG_STRING];
+ char type[LONG_STRING];
+
+ m_strcpy(type, sizeof(type), mtype);
+
+ if (option(OPTMAILCAPSANITIZE))
+ mutt_sanitize_filename(type, 0);
+
+ while (command[x] && x < clen && y < ssizeof(buf)) {
+ switch (command[x]) {
+ case '\\':
+ x++;
+ buf[y++] = command[x++];
+ break;
+
+ case '%':
+ x++;
+ if (command[x] == '{') {
+ char param[STRING];
+ char pval[STRING];
+ int z = 0;
+
+ x++;
+ while (command[x] && command[x] != '}' && z < ssizeof (param))
+ param[z++] = command[x++];
+ param[z] = '\0';
+
+ m_strcpy(pval, sizeof(pval),
+ mutt_get_parameter(param, a->parameter));
+
+ if (option(OPTMAILCAPSANITIZE))
+ mutt_sanitize_filename(pval, 0);
+
+ y += mutt_quote_filename(buf + y, sizeof(buf) - y, pval);
+ }
+
+ if (command[x] == 's' && filename) {
+ y += mutt_quote_filename(buf + y, sizeof(buf) - y, filename);
+ needspipe = FALSE;
+ }
+
+ if (command[x] == 't') {
+ y += mutt_quote_filename(buf + y, sizeof(buf) - y, type);
+ }
+ x++;
+ break;
+
+ default:
+ buf[y++] = command[x++];
+ break;
+ }
+ }
+
+ buf[y] = '\0';
+ m_strcpy(command, clen, buf);
+
+ return needspipe;
+}
+
+static char *parse_field(char *p, char **field, char **value)
+{
+ p = vskipspaces(p);
+ *field = p;
+ *value = NULL;
+
+ for (;;) {
+ switch (*p) {
+ case ';':
+ *p++ = '\0';
+ case '\0':
+ m_strrtrim(*field);
+ m_strrtrim(*value);
+ return p;
+
+ case '\\':
+ p += 1 + (p[1] != 0);
+ break;
+
+ case '=':
+ if (!*value) {
+ *p++ = '\0';
+ p = *value = vskipspaces(p);
+ continue;
+ }
+ /* falltrhrough */
+
+ default:
+ p++;
+ break;
+ }
+ }
+}
+
+static inline void
+parse_field_error(const char *type, const char *filename, int line)
+{
+ mutt_error(_("Improperly formated entry for type %s in \"%s\" line %d"),
+ type, filename, line);
+}
+
+/* rfc1524 mailcap file is of the format:
+ * base/type; command; extradefs
+ * type can be * for matching all
+ * base with no /type is an implicit wild
+ * command contains a %s for the filename to pass, default to pipe on stdin
+ * extradefs are of the form:
+ * def1="definition"; def2="define \;";
+ * line wraps with a \ at the end of the line
+ * # for comments
+ */
+static int
+rfc1524_mailcap_parse(BODY *a, const char *filename, const char *type,
+ rfc1524_entry *entry, int opt)
+{
+ FILE *fp;
+ char *buf = NULL;
+ ssize_t buflen;
+ char *ch;
+ char *field, *value;
+ int found = FALSE;
+ int copiousoutput;
+ int composecommand;
+ int editcommand;
+ int printcommand;
+ int btlen;
+ int line = 0;
+
+ /* find length of basetype */
+ if ((ch = strchr (type, '/')) == NULL)
+ return FALSE;
+ btlen = ch - type;
+
+ fp = fopen(filename, "r");
+ if (!fp)
+ goto error;
+
+ while (!found && (buf = mutt_read_line(buf, &buflen, fp, &line)) != NULL) {
+ /* ignore comments */
+ if (*buf == '#')
+ continue;
+
+ /* check type */
+ ch = parse_field(buf, &field, &value);
+ if (ascii_strcasecmp(field, type)
+ && (ascii_strncasecmp(field, type, btlen)
+ || (buf[btlen] != 0 && m_strcmp(buf + btlen, "/*"))))
+ continue;
+
+ /* next field is the viewcommand */
+ ch = parse_field(ch, &field, &value);
+ if (entry)
+ entry->command = m_strdup(field);
+
+ /* parse the optional fields */
+ found = TRUE;
+ copiousoutput = FALSE;
+ composecommand = FALSE;
+ editcommand = FALSE;
+ printcommand = FALSE;
+
+ while (*ch) {
+ ch = parse_field(ch, &field, &value);
+
+ switch (mime_which_token(field, -1)) {
+#define DO_CASE(token, field, expr) \
+ case token: \
+ if (value) { \
+ if (entry) \
+ m_strreplace(&entry->field, value); \
+ expr; \
+ } else { \
+ parse_field_error(type, filename, line); \
+ } \
+ break;
+
+ case MIME_NEEDSTERMINAL:
+ if (entry)
+ entry->needsterminal = TRUE;
+ break;
+
+ case MIME_COPIOUSOUTPUT:
+ copiousoutput = TRUE;
+ if (entry)
+ entry->copiousoutput = TRUE;
+ break;
+
+ DO_CASE(MIME_COMPOSETYPED, composecommand, composecommand = TRUE);
+ DO_CASE(MIME_COMPOSE, composecommand, composecommand = TRUE);
+ DO_CASE(MIME_PRINT, printcommand, printcommand = TRUE);
+ DO_CASE(MIME_EDIT, editcommand, editcommand = TRUE);
+ DO_CASE(MIME_NAMETEMPLATE, nametemplate, );
+ DO_CASE(MIME_X_CONVERT, convert, );
+
+ case MIME_TEST:
+ /*
+ * This routine executes the given test command to determine
+ * if this is the right entry. a non-zero exit code means
+ * test failed
+ */
+ if (value) {
+ ssize_t len = m_strlen(value) + STRING;
+ char *testcmd = p_new(char, len);
+
+ strcpy(testcmd, value);
+ rfc1524_expand_command(a, a->filename, type, testcmd, len);
+ found = !mutt_system(testcmd);
+ p_delete(&testcmd);
+ } else {
+ parse_field_error(type, filename, line);
+ }
+ break;
+
+ default:
+ break;
+#undef DO_CASE
+ }
+ }
+
+ if (opt == M_AUTOVIEW) {
+ if (!copiousoutput)
+ found = FALSE;
+ }
+ else if (opt == M_COMPOSE) {
+ if (!composecommand)
+ found = FALSE;
+ }
+ else if (opt == M_EDIT) {
+ if (!editcommand)
+ found = FALSE;
+ }
+ else if (opt == M_PRINT) {
+ if (!printcommand)
+ found = FALSE;
+ }
+
+ if (!found && entry) {
+ rfc1524_entry_wipe(entry);
+ rfc1524_entry_init(entry);
+ }
+ } /* while (!found && (buf = mutt_read_line ())) */
+ fclose (fp);
+
+ error:
+ p_delete(&buf);
+ return found;
+}
+
+
+/************** READ MARK **********************/
+
+/*
+ * rfc1524_mailcap_lookup attempts to find the given type in the
+ * list of mailcap files. On success, this returns the entry information
+ * in *entry, and returns 1. On failure (not found), returns 0.
+ * If entry == NULL just return 1 if the given type is found.
+ */
+int rfc1524_mailcap_lookup (BODY * a, char *type, rfc1524_entry * entry,
+ int opt)
+{
+ char path[_POSIX_PATH_MAX];
+ int x;
+ int found = FALSE;
+ char *curr = MailcapPath;
+
+ /* rfc1524 specifies that a path of mailcap files should be searched.
+ * joy. They say
+ * $HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap, etc
+ * and overriden by the MAILCAPS environment variable, and, just to be nice,
+ * we'll make it specifiable in .muttrc
+ */
+ if (!curr || !*curr) {
+ mutt_error _("No mailcap path specified");
+
+ return 0;
+ }
+
+ mutt_check_lookup_list (a, type, SHORT_STRING);
+
+ while (!found && *curr) {
+ x = 0;
+ while (*curr && *curr != ':' && x < ssizeof (path) - 1) {
+ path[x++] = *curr;
+ curr++;
+ }
+ if (*curr)
+ curr++;
+
+ if (!x)
+ continue;
+
+ path[x] = '\0';
+ mutt_expand_path (path, sizeof (path));
+
+ found = rfc1524_mailcap_parse (a, path, type, entry, opt);
+ }
+
+ if (entry && !found)
+ mutt_error (_("mailcap entry for type %s not found"), type);
+
+ return found;
+}
+
+
+/* This routine will create a _temporary_ filename matching the
+ * name template given if this needs to be done.
+ *
+ * Please note that only the last path element of the
+ * template and/or the old file name will be used for the
+ * comparison and the temporary file name.
+ *
+ * Returns 0 if oldfile is fine as is.
+ * Returns 1 if newfile specified
+ */
+
+int rfc1524_expand_filename (char *nametemplate,
+ char *oldfile, char *newfile, ssize_t nflen)
+{
+ int i, j, k, ps, r;
+ char *s;
+ short lmatch = 0, rmatch = 0;
+ char left[_POSIX_PATH_MAX];
+ char right[_POSIX_PATH_MAX];
+
+ newfile[0] = 0;
+
+ /* first, ignore leading path components.
+ */
+
+ if (nametemplate && (s = strrchr (nametemplate, '/')))
+ nametemplate = s + 1;
+
+ if (oldfile && (s = strrchr (oldfile, '/')))
+ oldfile = s + 1;
+
+ if (!nametemplate) {
+ if (oldfile)
+ m_strcpy(newfile, nflen, oldfile);
+ }
+ else if (!oldfile) {
+ mutt_expand_fmt (newfile, nflen, nametemplate, "mutt");
+ }
+ else { /* oldfile && nametemplate */
+
+
+ /* first, compare everything left from the "%s"
+ * (if there is one).
+ */
+
+ lmatch = 1;
+ ps = 0;
+ for (i = 0; nametemplate[i]; i++) {
+ if (nametemplate[i] == '%' && nametemplate[i + 1] == 's') {
+ ps = 1;
+ break;
+ }
+
+ /* note that the following will _not_ read beyond oldfile's end. */
+
+ if (lmatch && nametemplate[i] != oldfile[i])
+ lmatch = 0;
+ }
+
+ if (ps) {
+
+ /* If we had a "%s", check the rest. */
+
+ /* now, for the right part: compare everything right from
+ * the "%s" to the final part of oldfile.
+ *
+ * The logic here is as follows:
+ *
+ * - We start reading from the end.
+ * - There must be a match _right_ from the "%s",
+ * thus the i + 2.
+ * - If there was a left hand match, this stuff
+ * must not be counted again. That's done by the
+ * condition (j >= (lmatch ? i : 0)).
+ */
+
+ rmatch = 1;
+
+ for (r = 0, j = m_strlen(oldfile) - 1, k =
+ m_strlen(nametemplate) - 1;
+ j >= (lmatch ? i : 0) && k >= i + 2; j--, k--) {
+ if (nametemplate[k] != oldfile[j]) {
+ rmatch = 0;
+ break;
+ }
+ }
+
+ /* Now, check if we had a full match. */
+
+ if (k >= i + 2)
+ rmatch = 0;
+
+ if (lmatch)
+ *left = 0;
+ else
+ m_strncpy(left, sizeof(left), nametemplate, i);
+
+ if (rmatch)
+ *right = 0;
+ else
+ m_strcpy(right, sizeof(right), nametemplate + i + 2);
+
+ snprintf (newfile, nflen, "%s%s%s", left, oldfile, right);
+ }
+ else {
+ /* no "%s" in the name template. */
+ m_strcpy(newfile, nflen, nametemplate);
+ }
+ }
+
+ mutt_adv_mktemp (NULL, newfile, nflen);
+
+ return !(rmatch && lmatch);
+}
+
#include "sort.h"
#include "mx.h"
#include "nntp.h"
-#include "rfc1524.h"
void nntp_add_to_list (NNTP_SERVER * s, NNTP_DATA * d)
{
#include "sort.h"
#include "mx.h"
#include "mx_nntp.h"
-#include "rfc1524.h"
#include "nntp.h"
#include "sidebar.h"
#include "buffy.h"
#include "mutt.h"
#include "handler.h"
-#include "rfc1524.h"
#include "sort.h"
#include "thread.h"
#include "mx.h"
#include "mutt.h"
#include "handler.h"
#include "recvattach.h"
-#include "rfc1524.h"
#include "attach.h"
#include "mx.h"
#include "copy.h"
#include "state.h"
#include "handler.h"
#include "recvattach.h"
-#include "rfc1524.h"
#include "attach.h"
#include "mx.h"
#include "copy.h"
+++ /dev/null
-/*
- * Copyright notice from original mutt:
- * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
- *
- * This file is part of mutt-ng, see http://www.muttng.org/.
- * It's licensed under the GNU General Public License,
- * please see the file GPL in the top level source directory.
- */
-
-/*
- * rfc1524 defines a format for the Multimedia Mail Configuration, which
- * is the standard mailcap file format under Unix which specifies what
- * external programs should be used to view/compose/edit multimedia files
- * based on content type.
- *
- * This file contains various functions for implementing a fair subset of
- * rfc1524.
- */
-
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <lib-lib/mem.h>
-#include <lib-lib/str.h>
-#include <lib-lib/ascii.h>
-#include <lib-lib/macros.h>
-#include <lib-lib/file.h>
-
-#include <lib-sys/unix.h>
-
-#include "mutt.h"
-#include "rfc1524.h"
-#include "attach.h"
-
-/* The command semantics include the following:
- * %s is the filename that contains the mail body data
- * %t is the content type, like text/plain
- * %{parameter} is replaced by the parameter value from the content-type field
- * \% is %
- * Unsupported rfc1524 parameters: these would probably require some doing
- * by mutt, and can probably just be done by piping the message to metamail
- * %n is the integer number of sub-parts in the multipart
- * %F is "content-type filename" repeated for each sub-part
- *
- * In addition, this function returns a 0 if the command works on a file,
- * and 1 if the command works on a pipe.
- */
-int rfc1524_expand_command (BODY * a, char *filename, char *_type,
- char *command, int clen)
-{
- int x = 0, y = 0;
- int needspipe = TRUE;
- char buf[LONG_STRING];
- char type[LONG_STRING];
-
- m_strcpy(type, sizeof(type), _type);
-
- if (option (OPTMAILCAPSANITIZE))
- mutt_sanitize_filename (type, 0);
-
- while (command[x] && x < clen && y < ssizeof (buf)) {
- if (command[x] == '\\') {
- x++;
- buf[y++] = command[x++];
- }
- else if (command[x] == '%') {
- x++;
- if (command[x] == '{') {
- char param[STRING];
- char pvalue[STRING];
- char *_pvalue;
- int z = 0;
-
- x++;
- while (command[x] && command[x] != '}' && z < ssizeof (param))
- param[z++] = command[x++];
- param[z] = '\0';
-
- _pvalue = mutt_get_parameter (param, a->parameter);
- m_strcpy(pvalue, sizeof(pvalue), NONULL(_pvalue));
- if (option (OPTMAILCAPSANITIZE))
- mutt_sanitize_filename (pvalue, 0);
-
- y += mutt_quote_filename (buf + y, sizeof (buf) - y, pvalue);
- }
- else if (command[x] == 's' && filename != NULL) {
- y += mutt_quote_filename (buf + y, sizeof (buf) - y, filename);
- needspipe = FALSE;
- }
- else if (command[x] == 't') {
- y += mutt_quote_filename (buf + y, sizeof (buf) - y, type);
- }
- x++;
- }
- else
- buf[y++] = command[x++];
- }
- buf[y] = '\0';
- m_strcpy(command, clen, buf);
-
- return needspipe;
-}
-
-/* NUL terminates a rfc 1524 field,
- * returns start of next field or NULL */
-static char *get_field (char *s)
-{
- char *ch;
-
- if (!s)
- return NULL;
-
- while ((ch = strpbrk (s, ";\\")) != NULL) {
- if (*ch == '\\') {
- s = ch + 1;
- if (*s)
- s++;
- }
- else {
- *ch++ = '\0';
- ch = vskipspaces(ch);
- break;
- }
- }
- m_strrtrim(s);
- return ch;
-}
-
-static int get_field_text (char *field, char **entry,
- char *type, char *filename, int line)
-{
- field = vskipspaces(field);
- if (*field == '=') {
- if (entry) {
- field = vskipspaces(field + 1);
- m_strreplace(entry, field);
- }
- return 1;
- }
- else {
- mutt_error (_("Improperly formated entry for type %s in \"%s\" line %d"),
- type, filename, line);
- return 0;
- }
-}
-
-static int rfc1524_mailcap_parse (BODY * a,
- char *filename,
- char *type, rfc1524_entry * entry, int opt)
-{
- FILE *fp;
- char *buf = NULL;
- ssize_t buflen;
- char *ch;
- char *field;
- int found = FALSE;
- int copiousoutput;
- int composecommand;
- int editcommand;
- int printcommand;
- int btlen;
- int line = 0;
-
- /* rfc1524 mailcap file is of the format:
- * base/type; command; extradefs
- * type can be * for matching all
- * base with no /type is an implicit wild
- * command contains a %s for the filename to pass, default to pipe on stdin
- * extradefs are of the form:
- * def1="definition"; def2="define \;";
- * line wraps with a \ at the end of the line
- * # for comments
- */
-
- /* find length of basetype */
- if ((ch = strchr (type, '/')) == NULL)
- return FALSE;
- btlen = ch - type;
-
- if ((fp = fopen (filename, "r")) != NULL) {
- while (!found && (buf = mutt_read_line(buf, &buflen, fp, &line)) != NULL) {
- /* ignore comments */
- if (*buf == '#')
- continue;
-
- /* check type */
- ch = get_field (buf);
- if (ascii_strcasecmp (buf, type) && (ascii_strncasecmp (buf, type, btlen) || (buf[btlen] != 0 && /* implicit wild */
- m_strcmp(buf + btlen, "/*")))) /* wildsubtype */
- continue;
-
- /* next field is the viewcommand */
- field = ch;
- ch = get_field (ch);
- if (entry)
- entry->command = m_strdup(field);
-
- /* parse the optional fields */
- found = TRUE;
- copiousoutput = FALSE;
- composecommand = FALSE;
- editcommand = FALSE;
- printcommand = FALSE;
-
- while (ch) {
- field = ch;
- ch = get_field (ch);
-
- if (!ascii_strcasecmp (field, "needsterminal")) {
- if (entry)
- entry->needsterminal = TRUE;
- }
- else if (!ascii_strcasecmp (field, "copiousoutput")) {
- copiousoutput = TRUE;
- if (entry)
- entry->copiousoutput = TRUE;
- }
- else if (!ascii_strncasecmp (field, "composetyped", 12)) {
- /* this compare most occur before compose to match correctly */
- if (get_field_text
- (field + 12, entry ? &entry->composetypecommand : NULL, type,
- filename, line))
- composecommand = TRUE;
- }
- else if (!ascii_strncasecmp (field, "compose", 7)) {
- if (get_field_text
- (field + 7, entry ? &entry->composecommand : NULL, type,
- filename, line))
- composecommand = TRUE;
- }
- else if (!ascii_strncasecmp (field, "print", 5)) {
- if (get_field_text (field + 5, entry ? &entry->printcommand : NULL,
- type, filename, line))
- printcommand = TRUE;
- }
- else if (!ascii_strncasecmp (field, "edit", 4)) {
- if (get_field_text (field + 4, entry ? &entry->editcommand : NULL,
- type, filename, line))
- editcommand = TRUE;
- }
- else if (!ascii_strncasecmp (field, "nametemplate", 12)) {
- get_field_text (field + 12, entry ? &entry->nametemplate : NULL,
- type, filename, line);
- }
- else if (!ascii_strncasecmp (field, "x-convert", 9)) {
- get_field_text (field + 9, entry ? &entry->convert : NULL,
- type, filename, line);
- }
- else if (!ascii_strncasecmp (field, "test", 4)) {
- /*
- * This routine executes the given test command to determine
- * if this is the right entry.
- */
- char *test_command = NULL;
- ssize_t len;
-
- if (get_field_text (field + 4, &test_command, type, filename, line)
- && test_command) {
- len = m_strlen(test_command) + STRING;
- p_realloc(&test_command, len);
- rfc1524_expand_command (a, a->filename, type, test_command, len);
- if (mutt_system (test_command)) {
- /* a non-zero exit code means test failed */
- found = FALSE;
- }
- p_delete(&test_command);
- }
- }
- } /* while (ch) */
-
- if (opt == M_AUTOVIEW) {
- if (!copiousoutput)
- found = FALSE;
- }
- else if (opt == M_COMPOSE) {
- if (!composecommand)
- found = FALSE;
- }
- else if (opt == M_EDIT) {
- if (!editcommand)
- found = FALSE;
- }
- else if (opt == M_PRINT) {
- if (!printcommand)
- found = FALSE;
- }
-
- if (!found) {
- /* reset */
- if (entry) {
- p_delete(&entry->command);
- p_delete(&entry->composecommand);
- p_delete(&entry->composetypecommand);
- p_delete(&entry->editcommand);
- p_delete(&entry->printcommand);
- p_delete(&entry->nametemplate);
- p_delete(&entry->convert);
- entry->needsterminal = 0;
- entry->copiousoutput = 0;
- }
- }
- } /* while (!found && (buf = mutt_read_line ())) */
- fclose (fp);
- } /* if ((fp = fopen ())) */
- p_delete(&buf);
- return found;
-}
-
-rfc1524_entry *rfc1524_new_entry (void)
-{
- return p_new(rfc1524_entry, 1);
-}
-
-void rfc1524_free_entry (rfc1524_entry ** entry)
-{
- rfc1524_entry *p = *entry;
-
- p_delete(&p->command);
- p_delete(&p->testcommand);
- p_delete(&p->composecommand);
- p_delete(&p->composetypecommand);
- p_delete(&p->editcommand);
- p_delete(&p->printcommand);
- p_delete(&p->nametemplate);
- p_delete(entry);
-}
-
-/*
- * rfc1524_mailcap_lookup attempts to find the given type in the
- * list of mailcap files. On success, this returns the entry information
- * in *entry, and returns 1. On failure (not found), returns 0.
- * If entry == NULL just return 1 if the given type is found.
- */
-int rfc1524_mailcap_lookup (BODY * a, char *type, rfc1524_entry * entry,
- int opt)
-{
- char path[_POSIX_PATH_MAX];
- int x;
- int found = FALSE;
- char *curr = MailcapPath;
-
- /* rfc1524 specifies that a path of mailcap files should be searched.
- * joy. They say
- * $HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap, etc
- * and overriden by the MAILCAPS environment variable, and, just to be nice,
- * we'll make it specifiable in .muttrc
- */
- if (!curr || !*curr) {
- mutt_error _("No mailcap path specified");
-
- return 0;
- }
-
- mutt_check_lookup_list (a, type, SHORT_STRING);
-
- while (!found && *curr) {
- x = 0;
- while (*curr && *curr != ':' && x < ssizeof (path) - 1) {
- path[x++] = *curr;
- curr++;
- }
- if (*curr)
- curr++;
-
- if (!x)
- continue;
-
- path[x] = '\0';
- mutt_expand_path (path, sizeof (path));
-
- found = rfc1524_mailcap_parse (a, path, type, entry, opt);
- }
-
- if (entry && !found)
- mutt_error (_("mailcap entry for type %s not found"), type);
-
- return found;
-}
-
-
-/* This routine will create a _temporary_ filename matching the
- * name template given if this needs to be done.
- *
- * Please note that only the last path element of the
- * template and/or the old file name will be used for the
- * comparison and the temporary file name.
- *
- * Returns 0 if oldfile is fine as is.
- * Returns 1 if newfile specified
- */
-
-int rfc1524_expand_filename (char *nametemplate,
- char *oldfile, char *newfile, ssize_t nflen)
-{
- int i, j, k, ps, r;
- char *s;
- short lmatch = 0, rmatch = 0;
- char left[_POSIX_PATH_MAX];
- char right[_POSIX_PATH_MAX];
-
- newfile[0] = 0;
-
- /* first, ignore leading path components.
- */
-
- if (nametemplate && (s = strrchr (nametemplate, '/')))
- nametemplate = s + 1;
-
- if (oldfile && (s = strrchr (oldfile, '/')))
- oldfile = s + 1;
-
- if (!nametemplate) {
- if (oldfile)
- m_strcpy(newfile, nflen, oldfile);
- }
- else if (!oldfile) {
- mutt_expand_fmt (newfile, nflen, nametemplate, "mutt");
- }
- else { /* oldfile && nametemplate */
-
-
- /* first, compare everything left from the "%s"
- * (if there is one).
- */
-
- lmatch = 1;
- ps = 0;
- for (i = 0; nametemplate[i]; i++) {
- if (nametemplate[i] == '%' && nametemplate[i + 1] == 's') {
- ps = 1;
- break;
- }
-
- /* note that the following will _not_ read beyond oldfile's end. */
-
- if (lmatch && nametemplate[i] != oldfile[i])
- lmatch = 0;
- }
-
- if (ps) {
-
- /* If we had a "%s", check the rest. */
-
- /* now, for the right part: compare everything right from
- * the "%s" to the final part of oldfile.
- *
- * The logic here is as follows:
- *
- * - We start reading from the end.
- * - There must be a match _right_ from the "%s",
- * thus the i + 2.
- * - If there was a left hand match, this stuff
- * must not be counted again. That's done by the
- * condition (j >= (lmatch ? i : 0)).
- */
-
- rmatch = 1;
-
- for (r = 0, j = m_strlen(oldfile) - 1, k =
- m_strlen(nametemplate) - 1;
- j >= (lmatch ? i : 0) && k >= i + 2; j--, k--) {
- if (nametemplate[k] != oldfile[j]) {
- rmatch = 0;
- break;
- }
- }
-
- /* Now, check if we had a full match. */
-
- if (k >= i + 2)
- rmatch = 0;
-
- if (lmatch)
- *left = 0;
- else
- m_strncpy(left, sizeof(left), nametemplate, i);
-
- if (rmatch)
- *right = 0;
- else
- m_strcpy(right, sizeof(right), nametemplate + i + 2);
-
- snprintf (newfile, nflen, "%s%s%s", left, oldfile, right);
- }
- else {
- /* no "%s" in the name template. */
- m_strcpy(newfile, nflen, nametemplate);
- }
- }
-
- mutt_adv_mktemp (NULL, newfile, nflen);
-
- if (rmatch && lmatch)
- return 0;
- else
- return 1;
-
-}
-
-/* If rfc1524_expand_command() is used on a recv'd message, then
- * the filename doesn't exist yet, but if its used while sending a message,
- * then we need to rename the existing file.
- *
- * This function returns 0 on successful move, 1 on old file doesn't exist,
- * 2 on new file already exists, and 3 on other failure.
- */
-
-/* note on access(2) use: No dangling symlink problems here due to
- * safe_fopen().
- */
-
-int _mutt_rename_file (char *oldfile, char *newfile, int overwrite)
-{
- FILE *ofp, *nfp;
-
- if (access (oldfile, F_OK) != 0)
- return 1;
- if (!overwrite && access (newfile, F_OK) == 0)
- return 2;
- if ((ofp = fopen (oldfile, "r")) == NULL)
- return 3;
- if ((nfp = safe_fopen (newfile, "w")) == NULL) {
- fclose (ofp);
- return 3;
- }
- mutt_copy_stream (ofp, nfp);
- fclose (nfp);
- fclose (ofp);
- mutt_unlink (oldfile);
- return 0;
-}
-
-int mutt_rename_file (char *oldfile, char *newfile)
-{
- return _mutt_rename_file (oldfile, newfile, 0);
-}
+++ /dev/null
-/*
- * Copyright notice from original mutt:
- * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
- *
- * This file is part of mutt-ng, see http://www.muttng.org/.
- * It's licensed under the GNU General Public License,
- * please see the file GPL in the top level source directory.
- */
-
-#ifndef _RFC1524_H
-#define _RFC1524_H
-
-typedef struct rfc1524_mailcap_entry {
- /* char *contenttype; *//* we don't need this, as we search for it */
- char *command;
- char *testcommand;
- char *composecommand;
- char *composetypecommand;
- char *editcommand;
- char *printcommand;
- char *nametemplate;
- char *convert;
- /* char *description; *//* we don't need this */
- unsigned int needsterminal:1; /* endwin() and system */
- unsigned int copiousoutput:1; /* needs pager, basically */
-} rfc1524_entry;
-
-rfc1524_entry *rfc1524_new_entry (void);
-void rfc1524_free_entry (rfc1524_entry **);
-int rfc1524_expand_command (BODY *, char *, char *, char *, int);
-int rfc1524_expand_filename (char *, char *, char *, ssize_t);
-int rfc1524_mailcap_lookup (BODY *, char *, rfc1524_entry *, int);
-int mutt_rename_file (char *, char *);
-int _mutt_rename_file (char *, char *, int);
-
-#endif /* _RFC1524_H */