int *length;
} alblock;
-static uschar * fn_recipients(void);
typedef uschar * stringptr_fn_t(void);
+static uschar * fn_recipients(void);
static uschar * fn_queue_size(void);
/* This table must be kept in alphabetical order. */
{ "qualify_domain", vtype_stringptr, &qualify_domain_sender },
{ "qualify_recipient", vtype_stringptr, &qualify_domain_recipient },
{ "queue_name", vtype_stringptr, &queue_name },
- { "queue_size", vtype_string_func, &fn_queue_size },
+ { "queue_size", vtype_string_func, (void *) &fn_queue_size },
{ "rcpt_count", vtype_int, &rcpt_count },
{ "rcpt_defer_count", vtype_int, &rcpt_defer_count },
{ "rcpt_fail_count", vtype_int, &rcpt_fail_count },
*/
static uschar *
-find_header(uschar *name, int *newsize, unsigned flags, const uschar *charset)
+find_header(uschar * name, int * newsize, unsigned flags, const uschar * charset)
{
BOOL found = !name;
int len = name ? Ustrlen(name) : 0;
BOOL comma = FALSE;
gstring * g = NULL;
+uschar * rawhdr;
for (header_line * h = header_list; h; h = h->next)
if (h->type != htype_old && h->text) /* NULL => Received: placeholder */
/* That's all we do for raw header expansion. */
*newsize = g->size;
+rawhdr = string_from_gstring(g);
if (flags & FH_WANT_RAW)
- return string_from_gstring(g);
+ return rawhdr;
/* Otherwise do RFC 2047 decoding, translating the charset if requested.
The rfc2047_decode2() function can return an error with decoded data if the
else
{
- uschar * error, * decoded = rfc2047_decode2(string_from_gstring(g),
+ uschar * error, * decoded = rfc2047_decode2(rawhdr,
check_rfc2047_length, charset, '?', NULL, newsize, &error);
if (error)
DEBUG(D_any) debug_printf("*** error in RFC 2047 decoding: %s\n"
- " input was: %s\n", error, g->s);
- return decoded ? decoded : string_from_gstring(g);
+ " input was: %s\n", error, rawhdr);
+ return decoded ? decoded : rawhdr;
}
}
s = recipients_list[i].address;
g = string_append2_listele_n(g, US", ", s, Ustrlen(s));
}
-return g ? g->s : NULL;
+return string_from_gstring(g);
}
reset in the middle of the buffer will make it inaccessible. */
len = Ustrlen(value);
+ DEBUG(D_expand) debug_expansion_interim(US"value", value, len, !!(flags & ESI_SKIPPING));
if (!yield && newsize != 0)
{
yield = g;
continue;
}
- if (isdigit(*s))
+ if (isdigit(*s)) /* A $<n> variable */
{
int n;
s = read_cnumber(&n, s);
if (n >= 0 && n <= expand_nmax)
+ {
+ DEBUG(D_expand) debug_expansion_interim(US"value", expand_nstring[n], expand_nlength[n], !!(flags & ESI_SKIPPING));
yield = string_catn(yield, expand_nstring[n], expand_nlength[n]);
+ }
continue;
}
goto EXPAND_FAILED;
}
if (n >= 0 && n <= expand_nmax)
+ {
+ DEBUG(D_expand) debug_expansion_interim(US"value", expand_nstring[n], expand_nlength[n], !!(flags & ESI_SKIPPING));
yield = string_catn(yield, expand_nstring[n], expand_nlength[n]);
+ }
continue;
}
skipping, but "break" otherwise so we get debug output for the item
expansion. */
{
- int start = gstring_length(yield);
+ int expansion_start = gstring_length(yield);
switch(item_type)
{
/* Call an ACL from an expansion. We feed data in via $acl_arg1 - $acl_arg9.
yield = string_append(yield, 3,
US"Authentication-Results: ", sub_arg[0], US"; none");
- yield->ptr -= 6;
+ yield->ptr -= 6; /* ignore tha ": none" for now */
yield = authres_local(yield, sub_arg[0]);
yield = authres_iprev(yield);
if (o2m >= 0) for (; oldptr < yield->ptr; oldptr++)
{
- uschar *m = Ustrrchr(sub[1], yield->s[oldptr]);
+ uschar * m = Ustrrchr(sub[1], yield->s[oldptr]);
if (m)
{
int o = m - sub[1];
it was for good reason */
if (quoted) yield = string_catn(yield, US"\"", 1);
- yield = string_catn(yield, g->s, g->ptr);
+ yield = gstring_append(yield, g);
if (quoted) yield = string_catn(yield, US"\"", 1);
/* @$original_domain */
} /* EITEM_* switch */
/*NOTREACHED*/
- DEBUG(D_expand)
- if (yield && (start > 0 || *s)) /* only if not the sole expansion of the line */
+ DEBUG(D_expand) /* only if not the sole expansion of the line */
+ if (yield && (expansion_start > 0 || *s))
debug_expansion_interim(US"item-res",
- yield->s + start, yield->ptr - start, !!(flags & ESI_SKIPPING));
+ yield->s + expansion_start, yield->ptr - expansion_start,
+ !!(flags & ESI_SKIPPING));
continue;
NOT_ITEM: ;
/* Deal specially with operators that might take a certificate variable
as we do not want to do the usual expansion. For most, expand the string.*/
+
switch(c)
{
#ifndef DISABLE_TLS
to the main loop top. */
{
- int start = yield->ptr;
+ unsigned expansion_start = gstring_length(yield);
switch(c)
{
case EOP_BASE32:
{
- uschar *t;
+ uschar * t;
unsigned long int n = Ustrtoul(sub, &t, 10);
gstring * g = NULL;
- if (*t != 0)
+ if (*t)
{
expand_string_message = string_sprintf("argument for base32 "
"operator is \"%s\", which is not a decimal number", sub);
case EOP_UTF8CLEAN:
{
- int seq_len = 0, index = 0;
- int bytes_left = 0;
+ int seq_len = 0, index = 0, bytes_left = 0, complete;
long codepoint = -1;
- int complete;
uschar seq_buff[4]; /* accumulate utf-8 here */
/* Manually track tainting, as we deal in individual chars below */
- if (!yield->s || !yield->ptr)
+ if (!yield)
+ yield = string_get_tainted(Ustrlen(sub), sub);
+ else if (!yield->s || !yield->ptr)
+ {
yield->s = store_get(yield->size = Ustrlen(sub), sub);
+ gstring_reset(yield);
+ }
else if (is_incompatible(yield->s, sub))
gstring_rebuffer(yield, sub);
goto EXPAND_FAILED;
}
yield = string_cat(yield, s);
- DEBUG(D_expand) debug_printf_indent("yield: '%s'\n", yield->s);
+ DEBUG(D_expand) debug_printf_indent("yield: '%s'\n", string_from_gstring(yield));
break;
}
DEBUG(D_expand)
{
- const uschar * s = yield->s + start;
- int i = yield->ptr - start;
+ const uschar * res = string_from_gstring(yield);
+ const uschar * s = res + expansion_start;
+ int i = gstring_length(yield) - expansion_start;
BOOL tainted = is_tainted(s);
DEBUG(D_noutf8)
if (tainted)
{
debug_printf_indent("%s \\__", flags & ESI_SKIPPING ? "| " : " ");
- debug_print_taint(yield->s);
+ debug_print_taint(res);
}
}
else
debug_printf_indent("%s",
flags & ESI_SKIPPING
? UTF8_VERT " " : " " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ);
- debug_print_taint(yield->s);
+ debug_print_taint(res);
}
}
}
added to the string. If so, set up an empty string. Add a terminating zero. If
left != NULL, return a pointer to the terminator. */
-if (!yield)
- yield = string_get(1);
-(void) string_from_gstring(yield);
-if (left) *left = s;
+ {
+ uschar * res;
-/* Any stacking store that was used above the final string is no longer needed.
-In many cases the final string will be the first one that was got and so there
-will be optimal store usage. */
+ if (!yield)
+ yield = string_get(1);
+ res = string_from_gstring(yield);
+ if (left) *left = s;
-if (resetok) gstring_release_unused(yield);
-else if (resetok_p) *resetok_p = FALSE;
+ /* Any stacking store that was used above the final string is no longer needed.
+ In many cases the final string will be the first one that was got and so there
+ will be optimal store usage. */
-DEBUG(D_expand)
- {
- BOOL tainted = is_tainted(yield->s);
- DEBUG(D_noutf8)
+ if (resetok) gstring_release_unused(yield);
+ else if (resetok_p) *resetok_p = FALSE;
+
+ DEBUG(D_expand)
{
- debug_printf_indent("|--expanding: %.*s\n", (int)(s - string), string);
- debug_printf_indent("%sresult: %s\n",
- flags & ESI_SKIPPING ? "|-----" : "\\_____", yield->s);
- if (tainted)
+ BOOL tainted = is_tainted(res);
+ DEBUG(D_noutf8)
{
- debug_printf_indent("%s \\__", flags & ESI_SKIPPING ? "| " : " ");
- debug_print_taint(yield->s);
+ debug_printf_indent("|--expanding: %.*s\n", (int)(s - string), string);
+ debug_printf_indent("%sresult: %s\n",
+ flags & ESI_SKIPPING ? "|-----" : "\\_____", res);
+ if (tainted)
+ {
+ debug_printf_indent("%s \\__", flags & ESI_SKIPPING ? "| " : " ");
+ debug_print_taint(res);
+ }
+ if (flags & ESI_SKIPPING)
+ debug_printf_indent("\\___skipping: result is not used\n");
}
- if (flags & ESI_SKIPPING)
- debug_printf_indent("\\___skipping: result is not used\n");
- }
- else
- {
- debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
- "expanding: %.*s\n",
- (int)(s - string), string);
- debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
- "result: %s\n",
- flags & ESI_SKIPPING ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
- yield->s);
- if (tainted)
+ else
{
- debug_printf_indent("%s",
- flags & ESI_SKIPPING
- ? UTF8_VERT " " : " " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ);
- debug_print_taint(yield->s);
+ debug_printf_indent(UTF8_VERT_RIGHT UTF8_HORIZ UTF8_HORIZ
+ "expanding: %.*s\n",
+ (int)(s - string), string);
+ debug_printf_indent("%s" UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
+ "result: %s\n",
+ flags & ESI_SKIPPING ? UTF8_VERT_RIGHT : UTF8_UP_RIGHT,
+ res);
+ if (tainted)
+ {
+ debug_printf_indent("%s",
+ flags & ESI_SKIPPING
+ ? UTF8_VERT " " : " " UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ);
+ debug_print_taint(res);
+ }
+ if (flags & ESI_SKIPPING)
+ debug_printf_indent(UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
+ "skipping: result is not used\n");
}
- if (flags & ESI_SKIPPING)
- debug_printf_indent(UTF8_UP_RIGHT UTF8_HORIZ UTF8_HORIZ UTF8_HORIZ
- "skipping: result is not used\n");
}
- }
-if (textonly_p) *textonly_p = textonly;
-expand_level--;
-return yield->s;
+ if (textonly_p) *textonly_p = textonly;
+ expand_level--;
+ return res;
+ }
/* This is the failure exit: easiest to program with a goto. We still need
to update the pointer to the terminator, for cases of nested calls with "fail".