-/* $Cambridge: exim/src/src/expand.c,v 1.62 2006/09/19 14:31:07 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.66 2006/10/30 14:59:15 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
vtype_stringptr, /* value is address of pointer to string */
vtype_msgbody, /* as stringptr, but read when first required */
vtype_msgbody_end, /* ditto, the end of the message */
- vtype_msgheaders, /* the message's headers */
+ vtype_msgheaders, /* the message's headers, processed */
+ vtype_msgheaders_raw, /* the message's headers, unprocessed */
vtype_localpart, /* extract local part from string */
vtype_domain, /* extract domain from string */
vtype_recipients, /* extract recipients from recipients list */
{ "message_body_size", vtype_int, &message_body_size },
{ "message_exim_id", vtype_stringptr, &message_id },
{ "message_headers", vtype_msgheaders, NULL },
+ { "message_headers_raw", vtype_msgheaders_raw, NULL },
{ "message_id", vtype_stringptr, &message_id },
{ "message_linecount", vtype_int, &message_linecount },
{ "message_size", vtype_int, &message_size },
newsize return the size of memory block that was obtained; may be NULL
if exists_only is TRUE
want_raw TRUE if called for $rh_ or $rheader_ variables; no processing,
- other than concatenating, will be done on the header
+ other than concatenating, will be done on the header. Also used
+ for $message_headers_raw.
charset name of charset to translate MIME words to; used only if
want_raw is false; if NULL, no translation is done (this is
used for $bh_ and $bheader_)
while (isspace(*t)) t++; /* remove leading white space */
ilen = h->slen - (t - h->text); /* length to insert */
+ /* Unless wanted raw, remove trailing whitespace, including the
+ newline. */
+
+ if (!want_raw)
+ while (ilen > 0 && isspace(t[ilen-1])) ilen--;
+
/* Set comma = 1 if handling a single header and it's one of those
that contains an address list, except when asked for raw headers. Only
need to do this once. */
/* First pass - compute total store needed; second pass - compute
total store used, including this header. */
- size += ilen + comma;
+ size += ilen + comma + 1; /* +1 for the newline */
/* Second pass - concatentate the data, up to a maximum. Note that
the loop stops when size hits the limit. */
{
if (size > header_insert_maxlen)
{
- ilen -= size - header_insert_maxlen;
+ ilen -= size - header_insert_maxlen - 1;
comma = 0;
}
Ustrncpy(ptr, t, ilen);
ptr += ilen;
- if (comma != 0 && ilen > 0)
+
+ /* For a non-raw header, put in the comma if needed, then add
+ back the newline we removed above, provided there was some text in
+ the header. */
+
+ if (!want_raw && ilen > 0)
{
- ptr[-1] = ',';
+ if (comma != 0) *ptr++ = ',';
*ptr++ = '\n';
}
}
}
}
- /* At end of first pass, truncate size if necessary, and get the buffer
- to hold the data, returning the buffer size. */
+ /* At end of first pass, return NULL if no header found. Then truncate size
+ if necessary, and get the buffer to hold the data, returning the buffer size.
+ */
if (i == 0)
{
}
}
-/* Remove a redundant added comma if present */
-
-if (comma != 0 && ptr > yield) ptr -= 2;
-
/* That's all we do for raw header expansion. */
if (want_raw)
*ptr = 0;
}
-/* Otherwise, we remove trailing whitespace, including newlines. Then we do RFC
-2047 decoding, translating the charset if requested. The rfc2047_decode2()
+/* Otherwise, remove a final newline and a redundant added comma. Then we do
+RFC 2047 decoding, translating the charset if requested. The rfc2047_decode2()
function can return an error with decoded data if the charset translation
fails. If decoding fails, it returns NULL. */
else
{
uschar *decoded, *error;
- while (ptr > yield && isspace(ptr[-1])) ptr--;
+ if (ptr > yield && ptr[-1] == '\n') ptr--;
+ if (ptr > yield && comma != 0 && ptr[-1] == ',') ptr--;
*ptr = 0;
decoded = rfc2047_decode2(yield, check_rfc2047_length, charset, '?', NULL,
newsize, &error);
case vtype_msgheaders:
return find_header(NULL, exists_only, newsize, FALSE, NULL);
+ case vtype_msgheaders_raw:
+ return find_header(NULL, exists_only, newsize, TRUE, NULL);
+
case vtype_msgbody: /* Pointer to msgbody string */
case vtype_msgbody_end: /* Ditto, the end of the msg */
ss = (uschar **)(var_table[middle].value);
else
{
shost.name = server_name;
- if (host_find_byname(&shost, NULL, NULL, FALSE) != HOST_FOUND)
+ if (host_find_byname(&shost, NULL, HOST_FIND_QUALIFY_SINGLE, NULL,
+ FALSE) != HOST_FOUND)
{
expand_string_message =
string_sprintf("no IP address found for host %s", shost.name);