US"reduce",
US"run",
US"sg",
+ US"sort",
US"substr",
US"tr" };
EITEM_REDUCE,
EITEM_RUN,
EITEM_SG,
+ EITEM_SORT,
EITEM_SUBSTR,
EITEM_TR };
{ "host_data", vtype_stringptr, &host_data },
{ "host_lookup_deferred",vtype_int, &host_lookup_deferred },
{ "host_lookup_failed", vtype_int, &host_lookup_failed },
+ { "host_port", vtype_int, &deliver_host_port },
{ "inode", vtype_ino, &deliver_inode },
{ "interface_address", vtype_stringptr, &interface_address },
{ "interface_port", vtype_int, &interface_port },
{ "tls_out_bits", vtype_int, &tls_out.bits },
{ "tls_out_certificate_verified", vtype_int,&tls_out.certificate_verified },
{ "tls_out_cipher", vtype_stringptr, &tls_out.cipher },
+#ifdef EXPERIMENTAL_DANE
+ { "tls_out_dane", vtype_bool, &tls_out.dane_verified },
+#endif
{ "tls_out_ocsp", vtype_int, &tls_out.ocsp },
{ "tls_out_ourcert", vtype_cert, &tls_out.ourcert },
{ "tls_out_peercert", vtype_cert, &tls_out.peercert },
#if defined(SUPPORT_TLS)
{ "tls_out_sni", vtype_stringptr, &tls_out.sni },
#endif
+#ifdef EXPERIMENTAL_DANE
+ { "tls_out_tlsa_usage", vtype_int, &tls_out.tlsa_usage },
+#endif
{ "tls_peerdn", vtype_stringptr, &tls_in.peerdn }, /* mind the alphabetical order! */
#if defined(SUPPORT_TLS)
{ "tod_zone", vtype_todzone, NULL },
{ "tod_zulu", vtype_todzulu, NULL },
#ifdef EXPERIMENTAL_TPDA
+ { "tpda_data", vtype_stringptr, &tpda_data },
+
+ /*XXX want to use generic vars for as many of these as possible*/
{ "tpda_defer_errno", vtype_int, &tpda_defer_errno },
- { "tpda_defer_errstr", vtype_stringptr, &tpda_defer_errstr },
- { "tpda_delivery_confirmation", vtype_stringptr, &tpda_delivery_confirmation },
- { "tpda_delivery_domain", vtype_stringptr, &tpda_delivery_domain },
- { "tpda_delivery_fqdn", vtype_stringptr, &tpda_delivery_fqdn },
- { "tpda_delivery_ip", vtype_stringptr, &tpda_delivery_ip },
- { "tpda_delivery_local_part",vtype_stringptr,&tpda_delivery_local_part },
- { "tpda_delivery_port", vtype_int, &tpda_delivery_port },
+
+ { "tpda_event", vtype_stringptr, &tpda_event },
#endif
{ "transport_name", vtype_stringptr, &transport_name },
{ "value", vtype_stringptr, &lookup_value },
#ifdef HAVE_ARC4RANDOM
/* cryptographically strong randomness, common on *BSD platforms, not
so much elsewhere. Alas. */
+#ifndef NOT_HAVE_ARC4RANDOM_STIR
arc4random_stir();
+#endif
#elif defined(HAVE_SRANDOM) || defined(HAVE_SRANDOMDEV)
#ifdef HAVE_SRANDOMDEV
/* uses random(4) for seeding */
uschar *save_iterate_item = iterate_item;
int (*compare)(const uschar *, const uschar *);
+ DEBUG(D_expand) debug_printf("condition: %s\n", name);
+
tempcond = FALSE;
if (cond_type == ECOND_INLISTI)
compare = strcmpic;
int sep = 0;
uschar *save_iterate_item = iterate_item;
+ DEBUG(D_expand) debug_printf("condition: %s\n", name);
+
while (isspace(*s)) s++;
if (*s++ != '{') goto COND_FAILED_CURLY_START; /* }-for-text-editors */
sub[0] = expand_string_internal(s, TRUE, &s, (yield == NULL), TRUE, resetok);
while (len > 0 && isspace(p[len-1])) len--;
p[len] = 0;
- if (*p == 0 && !skipping)
- {
- expand_string_message = US"first argument of \"extract\" must "
- "not be empty";
- goto EXPAND_FAILED;
- }
+ if (!skipping)
+ {
+ if (*p == 0)
+ {
+ expand_string_message = US"first argument of \"extract\" must "
+ "not be empty";
+ goto EXPAND_FAILED;
+ }
- if (*p == '-')
- {
- field_number = -1;
- p++;
- }
- while (*p != 0 && isdigit(*p)) x = x * 10 + *p++ - '0';
- if (*p == 0)
- {
- field_number *= x;
- j = 3; /* Need 3 args */
- field_number_set = TRUE;
- }
+ if (*p == '-')
+ {
+ field_number = -1;
+ p++;
+ }
+ while (*p != 0 && isdigit(*p)) x = x * 10 + *p++ - '0';
+ if (*p == 0)
+ {
+ field_number *= x;
+ j = 3; /* Need 3 args */
+ field_number_set = TRUE;
+ }
+ }
}
}
else goto EXPAND_FAILED_CURLY;
continue;
}
+ case EITEM_SORT:
+ {
+ int sep = 0;
+ uschar *srclist, *cmp, *xtract;
+ uschar *srcitem;
+ uschar *dstlist = NULL;
+ uschar *dstkeylist = NULL;
+ uschar * tmp;
+ uschar *save_iterate_item = iterate_item;
+
+ while (isspace(*s)) s++;
+ if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+
+ srclist = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
+ if (!srclist) goto EXPAND_FAILED;
+ if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+
+ while (isspace(*s)) s++;
+ if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+
+ cmp = expand_string_internal(s, TRUE, &s, skipping, FALSE, &resetok);
+ if (!cmp) goto EXPAND_FAILED;
+ if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+
+ while (isspace(*s)) s++;
+ if (*s++ != '{') goto EXPAND_FAILED_CURLY;
+
+ xtract = s;
+ tmp = expand_string_internal(s, TRUE, &s, TRUE, TRUE, &resetok);
+ if (!tmp) goto EXPAND_FAILED;
+ xtract = string_copyn(xtract, s - xtract);
+
+ if (*s++ != '}') goto EXPAND_FAILED_CURLY;
+ /*{*/
+ if (*s++ != '}')
+ { /*{*/
+ expand_string_message = US"missing } at end of \"sort\"";
+ goto EXPAND_FAILED;
+ }
+
+ if (skipping) continue;
+
+ while ((srcitem = string_nextinlist(&srclist, &sep, NULL, 0)))
+ {
+ uschar * dstitem;
+ uschar * newlist = NULL;
+ uschar * newkeylist = NULL;
+ uschar * srcfield;
+
+ DEBUG(D_expand) debug_printf("%s: $item = \"%s\"\n", name, srcitem);
+
+ /* extract field for comparisons */
+ iterate_item = srcitem;
+ if ( !(srcfield = expand_string_internal(xtract, FALSE, NULL, FALSE,
+ TRUE, &resetok))
+ || !*srcfield)
+ {
+ expand_string_message = string_sprintf(
+ "field-extract in sort: \"%s\"", xtract);
+ goto EXPAND_FAILED;
+ }
+
+ /* Insertion sort */
+
+ /* copy output list until new-item < list-item */
+ while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
+ {
+ uschar * dstfield;
+ uschar * expr;
+ BOOL before;
+
+ /* field for comparison */
+ if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
+ goto sort_mismatch;
+
+ /* build and run condition string */
+ expr = string_sprintf("%s{%s}{%s}", cmp, srcfield, dstfield);
+
+ DEBUG(D_expand) debug_printf("%s: cond = \"%s\"\n", name, expr);
+ if (!eval_condition(expr, &resetok, &before))
+ {
+ expand_string_message = string_sprintf("comparison in sort: %s",
+ expr);
+ goto EXPAND_FAILED;
+ }
+
+ if (before)
+ {
+ /* New-item sorts before this dst-item. Append new-item,
+ then dst-item, then remainder of dst list. */
+
+ newlist = string_append_listele(newlist, sep, srcitem);
+ newkeylist = string_append_listele(newkeylist, sep, srcfield);
+ srcitem = NULL;
+
+ newlist = string_append_listele(newlist, sep, dstitem);
+ newkeylist = string_append_listele(newkeylist, sep, dstfield);
+
+ while ((dstitem = string_nextinlist(&dstlist, &sep, NULL, 0)))
+ {
+ if (!(dstfield = string_nextinlist(&dstkeylist, &sep, NULL, 0)))
+ goto sort_mismatch;
+ newlist = string_append_listele(newlist, sep, dstitem);
+ newkeylist = string_append_listele(newkeylist, sep, dstfield);
+ }
+
+ break;
+ }
+
+ newlist = string_append_listele(newlist, sep, dstitem);
+ newkeylist = string_append_listele(newkeylist, sep, dstfield);
+ }
+
+ /* If we ran out of dstlist without consuming srcitem, append it */
+ if (srcitem)
+ {
+ newlist = string_append_listele(newlist, sep, srcitem);
+ newkeylist = string_append_listele(newkeylist, sep, srcfield);
+ }
+
+ dstlist = newlist;
+ dstkeylist = newkeylist;
+
+ DEBUG(D_expand) debug_printf("%s: dstlist = \"%s\"\n", name, dstlist);
+ DEBUG(D_expand) debug_printf("%s: dstkeylist = \"%s\"\n", name, dstkeylist);
+ }
+
+ if (dstlist)
+ yield = string_cat(yield, &size, &ptr, dstlist, Ustrlen(dstlist));
+
+ /* Restore preserved $item */
+ iterate_item = save_iterate_item;
+ continue;
+
+ sort_mismatch:
+ expand_string_message = US"Internal error in sort (list mismatch)";
+ goto EXPAND_FAILED;
+ }
+
/* If ${dlfunc } support is configured, handle calling dynamically-loaded
functions, unless locked out at this time. Syntax is ${dlfunc{file}{func}}
case EOP_UTF8CLEAN:
{
- int seq_len, index = 0;
+ int seq_len = 0, index = 0;
int bytes_left = 0;
+ long codepoint = -1;
uschar seq_buff[4]; /* accumulate utf-8 here */
while (*sub != 0)
{
- int complete;
- long codepoint;
- uschar c;
+ int complete = 0;
+ uschar c = *sub++;
- complete = 0;
- c = *sub++;
if (bytes_left)
{
if ((c & 0xc0) != 0x80)
if (--bytes_left == 0) /* codepoint complete */
{
if(codepoint > 0x10FFFF) /* is it too large? */
- complete = -1; /* error */
+ complete = -1; /* error (RFC3629 limit) */
else
{ /* finished; output utf-8 sequence */
yield = string_cat(yield, &size, &ptr, seq_buff, seq_len);