. --- ID that ties them together.
. --- The index entry points to the most-recent chapter head, section or subsection
. --- head, or list-item.
+. ---- It'd be a lot nicer to point to the precise word-location; a chapter
+. ---- can be pretty big.
.macro cindex
&<indexterm role="concept">&
sender and recipient addresses, and it can be tested using the &%-bv%& and
&%-bvs%& command line options.
+.cindex router "verify mode"
+.cindex "verify mode" routers
When an address is being verified, the routers are run in &"verify mode"&. This
does not affect the way the routers work, but it is a state that can be
detected. By this means, a router can be skipped or made to behave differently
string expansion becoming too powerful.
Arguments:
- string the string to be expanded
+ s the string to be expanded
flags
brace_ends expansion is to stop at }
honour_dollar TRUE if $ is to be expanded,
FALSE if it's just another character
skipping TRUE for recursive calls when the value isn't actually going
to be used (to allow for optimisation)
+ exists_only return as soon as we have a char, for optimisation
left if not NULL, a pointer to the first character after the
expansion is placed here (typically used with brace_ends)
resetok_p if not NULL, pointer to flag - write FALSE if unsafe to reset
*/
static uschar *
-expand_string_internal(const uschar * string, esi_flags flags, const uschar ** left,
+expand_string_internal(const uschar * s, esi_flags flags, const uschar ** left,
BOOL *resetok_p, BOOL * textonly_p)
{
rmark reset_point = store_mark();
-gstring * yield = string_get(Ustrlen(string) + 64);
+gstring * yield = NULL;
int item_type;
-const uschar * s = string;
+const uschar * orig_string = s;
const uschar * save_expand_nstring[EXPAND_MAXN+1];
int save_expand_nlength[EXPAND_MAXN+1];
BOOL resetok = TRUE, first = TRUE, textonly = TRUE;
f.expand_string_forcedfail = FALSE;
expand_string_message = US"";
-if (is_tainted(string))
+if (is_tainted(s))
{
expand_string_message =
string_sprintf("attempt to expand tainted string '%s'", s);
goto EXPAND_FAILED;
}
+ {
+ int len = Ustrlen(s);
+ if (len) yield = string_get(len + 64);
+ }
+
while (*s)
{
uschar name[256];
+ if (flags & ESI_EXISTS_ONLY && gstring_length(yield) > 0) break;
+
DEBUG(D_expand)
{
debug_printf_indent("%V%V%s: %W\n",
BOOL tainted = is_tainted(res);
debug_printf_indent("%Vexpanded: %.*W\n",
"K---",
- (int)(s - string), string);
+ (int)(s - orig_string), orig_string);
debug_printf_indent("%Vresult: ",
flags & ESI_SKIPPING ? "K-----" : "\\_____");
if (*res || !(flags & ESI_SKIPPING))
if (left) *left = s;
DEBUG(D_expand)
{
- debug_printf_indent("%Vfailed to expand: %s\n", "K", string);
+ debug_printf_indent("%Vfailed to expand: %s\n", "K", orig_string);
debug_printf_indent("%Verror message: %s\n",
f.expand_string_forcedfail ? "K---" : "\\___", expand_string_message);
if (f.expand_string_forcedfail)
{ return US expand_string_2(CUS string, NULL); }
+/* Just return whether the string is non-empty after expansion */
+
+BOOL
+expand_string_nonempty(const uschar * string)
+{
+const uschar * s;
+if (!string) return FALSE;
+s = expand_string_internal(string, ESI_HONOR_DOLLAR | ESI_EXISTS_ONLY,
+ NULL, NULL, NULL);
+return s && *s;
+}
if (cutthrough.delivery)
{
- if (addr->transport->filter_command)
+ if (expand_string_nonempty(addr->transport->filter_command))
{
cutthrough.delivery= FALSE;
HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of transport filter\n");
}
#ifndef DISABLE_DKIM
- /* DKIM signing needs to add a header after seeing the whole body, so we cannot just copy
- body bytes to the outbound as they are received, which is the intent of cutthrough. */
- if (ob->dkim.dkim_domain)
+ /* DKIM signing needs to add a header after seeing the whole body, so we
+ cannot just copy body bytes to the outbound as they are received, which is
+ the intent of cutthrough. */
+ if (expand_string_nonempty(ob->dkim.dkim_domain))
{
cutthrough.delivery= FALSE;
HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of DKIM signing\n");
}
#endif
#ifdef EXPERIMENTAL_ARC
- if (ob->arc_sign)
+ /* ARC has the same issue as DKIM above */
+ if (expand_string_nonempty(ob->arc_sign))
{
cutthrough.delivery= FALSE;
HDEBUG(D_acl|D_v) debug_printf("Cutthrough cancelled by presence of ARC signing\n");