* Exim - an Internet mail transport agent *
*************************************************/
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) The Exim Maintainers 2020 - 2023 */
+/* Copyright (c) University of Cambridge 1995 - 2018 */
/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* This file contains a function for decoding message header lines that may
contain encoded "words" according to the rules described in
int len = 0;
uschar *ptr;
-ptr = *ptrptr = store_get(Ustrlen(string) + 1); /* No longer than this */
+ptr = *ptrptr = store_get(Ustrlen(string) + 1, string); /* No longer than this */
while (*string != 0)
{
- register int ch = *string++;
+ int ch = *string++;
if (ch == '_') *ptr++ = ' ';
else if (ch == '=')
encoding = toupper((*q1ptr)[1]);
**endptr = 0;
if (encoding == 'B')
- dlen = b64decode(*q2ptr+1, dptrptr);
+ dlen = b64decode(*q2ptr+1, dptrptr, *q2ptr+1);
else if (encoding == 'Q')
dlen = rfc2047_qpdecode(*q2ptr+1, dptrptr);
**endptr = '?'; /* restore */
*/
uschar *
-rfc2047_decode2(uschar *string, BOOL lencheck, uschar *target, int zeroval,
- int *lenptr, int *sizeptr, uschar **error)
+rfc2047_decode2(uschar *string, BOOL lencheck, const uschar *target,
+ int zeroval, int *lenptr, int *sizeptr, uschar **error)
{
-int ptr = 0;
int size = Ustrlen(string);
size_t dlen;
-uschar *dptr, *yield;
-uschar *mimeword, *q1, *q2, *endword;
+uschar * dptr;
+gstring * yield;
+uschar * mimeword, * q1, * q2, * endword;
*error = NULL;
mimeword = decode_mimeword(string, lencheck, &q1, &q2, &endword, &dlen, &dptr);
-if (mimeword == NULL)
+if (!mimeword)
{
- if (lenptr != NULL) *lenptr = size;
+ if (lenptr) *lenptr = size;
return string;
}
translated into a multibyte code such as UTF-8. That's why we use the dynamic
string building code. */
-yield = store_get(++size);
+yield = string_get_tainted(++size, string);
-while (mimeword != NULL)
+while (mimeword)
{
- #if HAVE_ICONV
+#if HAVE_ICONV
iconv_t icd = (iconv_t)(-1);
- #endif
+#endif
if (mimeword != string)
- yield = string_cat(yield, &size, &ptr, string, mimeword - string);
+ yield = string_catn(yield, string, mimeword - string);
+/*XXX that might have to convert an untainted string to a tainted one */
/* Do a charset translation if required. This is supported only on hosts
that have the iconv() function. Translation errors set error, but carry on,
of long strings - the RFC puts limits on the length, but it's best to be
robust. */
- #if HAVE_ICONV
+#if HAVE_ICONV
*q1 = 0;
- if (target != NULL && strcmpic(target, mimeword+2) != 0)
- {
- icd = iconv_open(CS target, CS(mimeword+2));
-
- if (icd == (iconv_t)(-1))
- {
+ if (target && strcmpic(target, mimeword+2) != 0)
+ if ((icd = iconv_open(CS target, CS(mimeword+2))) == (iconv_t)-1)
*error = string_sprintf("iconv_open(\"%s\", \"%s\") failed: %s%s",
target, mimeword+2, strerror(errno),
(errno == EINVAL)? " (maybe unsupported conversion)" : "");
- }
- }
*q1 = '?';
- #endif
+#endif
while (dlen > 0)
{
uschar *tptr = NULL; /* Stops compiler warning */
int tlen = -1;
- #if HAVE_ICONV
+#if HAVE_ICONV
uschar tbuffer[256];
uschar *outptr = tbuffer;
size_t outleft = sizeof(tbuffer);
}
}
- #endif
+#endif
/* No charset translation is happening or there was a translation error;
just set up the original as the string to be added, and mark it all used.
/* Deal with zero values; convert them if requested. */
if (zeroval != 0)
- {
- int i;
- for (i = 0; i < tlen; i++)
+ for (int i = 0; i < tlen; i++)
if (tptr[i] == 0) tptr[i] = zeroval;
- }
/* Add the new string onto the result */
- yield = string_cat(yield, &size, &ptr, tptr, tlen);
+ yield = string_catn(yield, tptr, tlen);
}
- #if HAVE_ICONV
+#if HAVE_ICONV
if (icd != (iconv_t)(-1)) iconv_close(icd);
- #endif
+#endif
/* Update string past the MIME word; skip any white space if the next thing
is another MIME word. */
string = endword + 2;
mimeword = decode_mimeword(string, lencheck, &q1, &q2, &endword, &dlen, &dptr);
- if (mimeword != NULL)
+ if (mimeword)
{
uschar *s = string;
while (isspace(*s)) s++;
/* Copy the remaining characters of the string, zero-terminate it, and return
the length as well if requested. */
-yield = string_cat(yield, &size, &ptr, string, Ustrlen(string));
-yield[ptr] = 0;
-if (lenptr != NULL) *lenptr = ptr;
-if (sizeptr != NULL) *sizeptr = size;
-return yield;
+yield = string_cat(yield, string);
+
+if (lenptr) *lenptr = yield->ptr;
+if (sizeptr) *sizeptr = yield->size;
+return string_from_gstring(yield);
}
argument. */
uschar *
-rfc2047_decode(uschar *string, BOOL lencheck, uschar *target, int zeroval,
+rfc2047_decode(uschar *string, BOOL lencheck, const uschar *target, int zeroval,
int *lenptr, uschar **error)
{
return rfc2047_decode2(string, lencheck, target, zeroval, lenptr, NULL, error);