* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004, 2015
+/* Copyright (c) Tom Kistner <tom@duncanthrax.net> 2004 - 2015
* License: GPL
- * Copyright (c) The Exim Maintainers 2016
+ * Copyright (c) The Exim Maintainers 2015 - 2018
*/
#include "exim.h"
uschar *mime_current_boundary = NULL;
static mime_header mime_header_list[] = {
+ /* name namelen value */
{ US"content-type:", 13, &mime_content_type },
{ US"content-disposition:", 20, &mime_content_disposition },
{ US"content-transfer-encoding:", 26, &mime_content_transfer_encoding },
static int mime_header_list_size = nelem(mime_header_list);
static mime_parameter mime_parameter_list[] = {
+ /* name namelen value */
{ US"name=", 5, &mime_filename },
{ US"filename=", 9, &mime_filename },
{ US"charset=", 8, &mime_charset },
{
int sep = 0;
const uschar *list = *listptr;
-uschar *option;
-uschar option_buffer[1024];
-uschar decode_path[1024];
+uschar * option;
+uschar * decode_path;
FILE *decode_file = NULL;
long f_pos = 0;
ssize_t size_counter = 0;
return FAIL;
/* build default decode path (will exist since MBOX must be spooled up) */
-(void)string_format(decode_path,1024,"%s/scan/%s",spool_directory,message_id);
+decode_path = string_sprintf("%s/scan/%s", spool_directory, message_id);
/* try to find 1st option */
-if ((option = string_nextinlist(&list, &sep,
- option_buffer,
- sizeof(option_buffer))) != NULL)
+if ((option = string_nextinlist(&list, &sep, NULL, 0)))
{
/* parse 1st option */
if ((Ustrcmp(option,"false") == 0) || (Ustrcmp(option,"0") == 0))
if ( ((c == '\t') || (c == ' ')) && (header_value_mode == 1) )
continue;
- /* we have hit a non-whitespace char, start copying value data */
- header_value_mode = 2;
+ /* we have hit a non-whitespace char, start copying value data */
+ header_value_mode = 2;
- if (c == '"') /* flip "quoted" mode */
- header_value_mode = header_value_mode==2 ? 3 : 2;
+ if (c == '"') /* flip "quoted" mode */
+ header_value_mode = header_value_mode==2 ? 3 : 2;
- /* leave value mode on unquoted ';' */
- if (header_value_mode == 2 && c == ';') {
- header_value_mode = 0;
- };
- /* -------------------------------- */
+ /* leave value mode on unquoted ';' */
+ if (header_value_mode == 2 && c == ';')
+ header_value_mode = 0;
+ /* -------------------------------- */
}
else
{
header[num_copied] = '\0';
/* return 0 for EOF or empty line */
-if ((c == EOF) || (num_copied == 1))
- return 0;
-else
- return 1;
+return c == EOF || num_copied == 1 ? 0 : 1;
}
mime_param_val(uschar ** sp)
{
uschar * s = *sp;
-uschar * val = NULL;
-int size = 0, ptr = 0;
+gstring * val = NULL;
/* debug_printf_indent(" considering paramval '%s'\n", s); */
{
s++; /* skip opening " */
while (*s && *s != '"') /* " protects ; */
- val = string_catn(val, &size, &ptr, s++, 1);
+ val = string_catn(val, s++, 1);
if (*s) s++; /* skip closing " */
}
else
- val = string_catn(val, &size, &ptr, s++, 1);
-if (val) val[ptr] = '\0';
+ val = string_catn(val, s++, 1);
*sp = s;
-return val;
+return string_from_gstring(val);
}
static uschar *
static uschar *
rfc2231_to_2047(const uschar * fname, const uschar * charset, int * len)
{
-int size = 0, ptr = 0;
-uschar * val = string_catn(NULL, &size, &ptr, US"=?", 2);
+gstring * val = string_catn(NULL, US"=?", 2);
uschar c;
if (charset)
- val = string_cat(val, &size, &ptr, charset);
-val = string_catn(val, &size, &ptr, US"?Q?", 3);
+ val = string_cat(val, charset);
+val = string_catn(val, US"?Q?", 3);
while ((c = *fname))
if (c == '%' && isxdigit(fname[1]) && isxdigit(fname[2]))
{
- val = string_catn(val, &size, &ptr, US"=", 1);
- val = string_catn(val, &size, &ptr, ++fname, 2);
+ val = string_catn(val, US"=", 1);
+ val = string_catn(val, ++fname, 2);
fname += 2;
}
else
- val = string_catn(val, &size, &ptr, fname++, 1);
+ val = string_catn(val, fname++, 1);
-val = string_catn(val, &size, &ptr, US"?=", 2);
-val[*len = ptr] = '\0';
-return val;
+val = string_catn(val, US"?=", 2);
+*len = val->ptr;
+return string_from_gstring(val);
}
uschar * header = NULL;
struct mime_boundary_context nested_context;
-/* reserve a line buffer to work in */
-header = store_get(MIME_MAX_HEADER_SIZE+1);
+/* reserve a line buffer to work in. Assume tainted data. */
+header = store_get(MIME_MAX_HEADER_SIZE+1, TRUE);
/* Not actually used at the moment, but will be vital to fixing
* some RFC 2046 nonconformance later... */
/* parse headers, set up expansion variables */
while (mime_get_header(f, header))
- {
- struct mime_header * mh;
/* look for interesting headers */
- for (mh = mime_header_list;
+ for (struct mime_header * mh = mime_header_list;
mh < mime_header_list + mime_header_list_size;
mh++) if (strncmpic(mh->name, header, mh->namelen) == 0)
{
while (*p)
{
- mime_parameter * mp;
-
DEBUG(D_acl) debug_printf_indent("MIME: considering paramlist '%s'\n", p);
if ( !mime_filename
NULL, &err_msg);
DEBUG(D_acl) debug_printf_indent("MIME: plain-name %s\n", temp_string);
- size = Ustrlen(temp_string);
-
- if (size == slen)
+ if (!temp_string || (size = Ustrlen(temp_string)) == slen)
decoding_failed = TRUE;
else
/* build up a decoded filename over successive
else
/* look for interesting parameters */
- for (mp = mime_parameter_list;
+ for (mime_parameter * mp = mime_parameter_list;
mp < mime_parameter_list + nelem(mime_parameter_list);
mp++
) if (strncmpic(mp->name, p, mp->namelen) == 0)
}
}
}
- }
/* set additional flag variables (easier access) */
if ( mime_content_type