-/* $Cambridge: exim/src/src/expand.c,v 1.89 2007/08/22 10:10:23 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.96 2008/08/07 11:05:03 fanf2 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
{ "compile_date", vtype_stringptr, &version_date },
{ "compile_number", vtype_stringptr, &version_cnumber },
{ "csa_status", vtype_stringptr, &csa_status },
+#ifdef EXPERIMENTAL_DCC
+ { "dcc_header", vtype_stringptr, &dcc_header },
+ { "dcc_result", vtype_stringptr, &dcc_result },
+#endif
#ifdef WITH_OLD_DEMIME
{ "demime_errorlevel", vtype_int, &demime_errorlevel },
{ "demime_reason", vtype_stringptr, &demime_reason },
{ "dk_signsall", vtype_dk_verify, NULL },
{ "dk_status", vtype_dk_verify, NULL },
{ "dk_testing", vtype_dk_verify, NULL },
+#endif
+#ifdef EXPERIMENTAL_DKIM
+ { "dkim_domain", vtype_stringptr, &dkim_signing_domain },
+ { "dkim_selector", vtype_stringptr, &dkim_signing_selector },
#endif
{ "dnslist_domain", vtype_stringptr, &dnslist_domain },
{ "dnslist_matched", vtype_stringptr, &dnslist_matched },
{ "spam_score_int", vtype_stringptr, &spam_score_int },
#endif
#ifdef EXPERIMENTAL_SPF
+ { "spf_guess", vtype_stringptr, &spf_guess },
{ "spf_header_comment", vtype_stringptr, &spf_header_comment },
{ "spf_received", vtype_stringptr, &spf_received },
{ "spf_result", vtype_stringptr, &spf_result },
if (len > 0)
{
body[len] = 0;
- while (len > 0)
+ if (message_body_newlines) /* Separate loops for efficiency */
{
- if (body[--len] == '\n' || body[len] == 0) body[len] = ' ';
+ while (len > 0)
+ { if (body[--len] == 0) body[len] = ' '; }
+ }
+ else
+ {
+ while (len > 0)
+ { if (body[--len] == '\n' || body[len] == 0) body[len] = ' '; }
}
}
}
use that without copying. This is helpful for expanding strings like
$message_headers which can get very long.
+There's a problem if a ${dlfunc item has side-effects that cause allocation,
+since resetting the store at the end of the expansion will free store that was
+allocated by the plugin code as well as the slop after the expanded string. So
+we skip any resets if ${dlfunc has been used. This is an unfortunate
+consequence of string expansion becoming too powerful.
+
Arguments:
string the string to be expanded
ket_ends true if expansion is to stop at }
uschar *s = string;
uschar *save_expand_nstring[EXPAND_MAXN+1];
int save_expand_nlength[EXPAND_MAXN+1];
+BOOL resetok = TRUE;
expand_string_forcedfail = FALSE;
expand_string_message = US"";
if (ptr == 0 && yield != NULL)
{
- store_reset(yield);
+ if (resetok) store_reset(yield);
yield = NULL;
size = 0;
}
Adjust "inow" accordingly. */
if ( (iexpire < 7) && (inow >= 993) ) inow = 0;
- if (iexpire > inow)
+ if (iexpire >= inow)
{
prvscheck_result = US"1";
DEBUG(D_expand) debug_printf("prvscheck: success, $pvrs_result set to 1\n");
while (len > 0 && isspace(p[len-1])) len--;
p[len] = 0;
- if (*p == 0)
+ if (*p == 0 && !skipping)
{
expand_string_message = US"first argument of \"extract\" must "
"not be empty";
returns OK, we have a replacement string; if it returns DEFER then
expansion has failed in a non-forced manner; if it returns FAIL then
failure was forced; if it returns ERROR or any other value there's a
- problem, so panic slightly. */
+ problem, so panic slightly. In any case, assume that the function has
+ side-effects on the store that must be preserved. */
+ resetok = FALSE;
result = NULL;
for (argc = 0; argv[argc] != NULL; argc++);
status = func(&result, argc - 2, &argv[2]);
int newsize = 0;
if (ptr == 0)
{
- store_reset(yield);
+ if (resetok) store_reset(yield);
yield = NULL;
size = 0;
}
In many cases the final string will be the first one that was got and so there
will be optimal store usage. */
-store_reset(yield + ptr + 1);
+if (resetok) store_reset(yield + ptr + 1);
DEBUG(D_expand)
{
debug_printf("expanding: %.*s\n result: %s\n", (int)(s - string), string,