Make ${base62d: adjust for BASE_62, as ${base62: does.
[exim.git] / src / src / expand.c
index 632b1d933e4d437ab4a7748eb07a0f5e9ccedb3b..739f5e8545a61d3a139ebadad2368b4b4854a61e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/expand.c,v 1.36 2005/06/27 14:29:43 ph10 Exp $ */
+/* $Cambridge: exim/src/src/expand.c,v 1.43 2005/09/28 10:46:48 ph10 Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -399,6 +399,7 @@ static var_entry var_table[] = {
   { "message_body",        vtype_msgbody,     &message_body },
   { "message_body_end",    vtype_msgbody_end, &message_body_end },
   { "message_body_size",   vtype_int,         &message_body_size },
+  { "message_exim_id",     vtype_stringptr,   &message_id },
   { "message_headers",     vtype_msgheaders,  NULL },
   { "message_id",          vtype_stringptr,   &message_id },
   { "message_linecount",   vtype_int,         &message_linecount },
@@ -481,7 +482,8 @@ static var_entry var_table[] = {
   { "sender_rcvhost",      vtype_stringptr,   &sender_rcvhost },
   { "sender_verify_failure",vtype_stringptr,  &sender_verify_failure },
   { "smtp_active_hostname", vtype_stringptr,  &smtp_active_hostname },
-  { "smtp_command_argument", vtype_stringptr, &smtp_command_argument },
+  { "smtp_command",        vtype_stringptr,   &smtp_cmd_buffer },
+  { "smtp_command_argument", vtype_stringptr, &smtp_cmd_argument },
   { "sn0",                 vtype_filter_int,  &filter_sn[0] },
   { "sn1",                 vtype_filter_int,  &filter_sn[1] },
   { "sn2",                 vtype_filter_int,  &filter_sn[2] },
@@ -1426,7 +1428,10 @@ while (last > first)
     s = find_header(US"reply-to:", exists_only, newsize, FALSE,
       headers_charset);
     if (s == NULL || *s == 0)
+      {
+      *newsize = 0;                            /* For the *s==0 case */
       s = find_header(US"from:", exists_only, newsize, FALSE, headers_charset);
+      }
     return (s == NULL)? US"" : s;
 
     /* A recipients list is available only during system message filtering,
@@ -2745,12 +2750,14 @@ uschar *s = *sptr;
 int x = eval_term(&s, decimal, error);
 if (*error == NULL)
   {
-  while (*s == '*' || *s == '/')
+  while (*s == '*' || *s == '/' || *s == '%')
     {
     int op = *s++;
     int y = eval_term(&s, decimal, error);
     if (*error != NULL) break;
-    if (op == '*') x *= y; else x /= y;
+    if (op == '*') x *= y;
+      else if (op == '/') x /= y;
+      else x %= y;
     }
   }
 *sptr = s;
@@ -3125,7 +3132,7 @@ while (*s != 0)
       /* Check that a key was provided for those lookup types that need it,
       and was not supplied for those that use the query style. */
 
-      if (!mac_islookup(stype, lookup_querystyle))
+      if (!mac_islookup(stype, lookup_querystyle|lookup_absfilequery))
         {
         if (key == NULL)
           {
@@ -3145,7 +3152,9 @@ while (*s != 0)
         }
 
       /* Get the next string in brackets and expand it. It is the file name for
-      single-key+file lookups, and the whole query otherwise. */
+      single-key+file lookups, and the whole query otherwise. In the case of
+      queries that also require a file name (e.g. sqlite), the file name comes
+      first. */
 
       if (*s != '{') goto EXPAND_FAILED_CURLY;
       filename = expand_string_internal(s+1, TRUE, &s, skipping);
@@ -3154,12 +3163,30 @@ while (*s != 0)
       while (isspace(*s)) s++;
 
       /* If this isn't a single-key+file lookup, re-arrange the variables
-      to be appropriate for the search_ functions. */
+      to be appropriate for the search_ functions. For query-style lookups,
+      there is just a "key", and no file name. For the special query-style +
+      file types, the query (i.e. "key") starts with a file name. */
 
       if (key == NULL)
         {
+        while (isspace(*filename)) filename++;
         key = filename;
-        filename = NULL;
+
+        if (mac_islookup(stype, lookup_querystyle))
+          {
+          filename = NULL;
+          }
+        else
+          {
+          if (*filename != '/')
+            {
+            expand_string_message = string_sprintf(
+              "absolute file name expected for \"%s\" lookup", name);
+            goto EXPAND_FAILED;
+            }
+          while (*key != 0 && !isspace(*key)) key++;
+          if (*key != 0) *key++ = 0;
+          }
         }
 
       /* If skipping, don't do the next bit - just lookup_value == NULL, as if
@@ -4331,6 +4358,8 @@ while (*s != 0)
         continue;
         }
 
+      /* Note that for Darwin and Cygwin, BASE_62 actually has the value 36 */
+
       case EOP_BASE62D:
         {
         uschar buf[16];
@@ -4342,10 +4371,11 @@ while (*s != 0)
           if (t == NULL)
             {
             expand_string_message = string_sprintf("argument for base62d "
-              "operator is \"%s\", which is not a base 62 number", sub);
+              "operator is \"%s\", which is not a base %d number", sub,
+              BASE_62);
             goto EXPAND_FAILED;
             }
-          n = n * 62 + (t - base62_chars);
+          n = n * BASE_62 + (t - base62_chars);
           }
         (void)sprintf(CS buf, "%ld", n);
         yield = string_cat(yield, &size, &ptr, buf, Ustrlen(buf));
@@ -4825,6 +4855,12 @@ while (*s != 0)
         mode_t mode;
         struct stat st;
 
+        if ((expand_forbid & RDO_EXISTS) != 0)
+          {
+          expand_string_message = US"Use of the stat() expansion is not permitted";
+          goto EXPAND_FAILED;
+          }
+
         if (stat(CS sub, &st) < 0)
           {
           expand_string_message = string_sprintf("stat(%s) failed: %s",