X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=rfc1524.c;fp=rfc1524.c;h=0000000000000000000000000000000000000000;hp=bef11445a063efb3fcf5f6955582ce933ea5f886;hb=49081299c673ceebc38d9a4f0985608cb3aecfce;hpb=ebc89176d4b5d2b1363114bd716c7f7fcb2464aa diff --git a/rfc1524.c b/rfc1524.c deleted file mode 100644 index bef1144..0000000 --- a/rfc1524.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Copyright notice from original mutt: - * Copyright (C) 1996-2000 Michael R. Elkins - * - * 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 -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#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); -}