tidying
[exim.git] / src / src / expand.c
index a0b36f7e2268fd0d5741fa9e2dc87dc355227f67..a7edaae4728521fb613e63a3603a134bd0cbf4b1 100644 (file)
@@ -199,12 +199,15 @@ enum {
 static uschar *op_table_main[] = {
   US"address",
   US"addresses",
+  US"base32",
+  US"base32d",
   US"base62",
   US"base62d",
   US"base64",
   US"base64d",
   US"domain",
   US"escape",
+  US"escape8bit",
   US"eval",
   US"eval10",
   US"expand",
@@ -242,12 +245,15 @@ static uschar *op_table_main[] = {
 enum {
   EOP_ADDRESS =  nelem(op_table_underscore),
   EOP_ADDRESSES,
+  EOP_BASE32,
+  EOP_BASE32D,
   EOP_BASE62,
   EOP_BASE62D,
   EOP_BASE64,
   EOP_BASE64D,
   EOP_DOMAIN,
   EOP_ESCAPE,
+  EOP_ESCAPE8BIT,
   EOP_EVAL,
   EOP_EVAL10,
   EOP_EXPAND,
@@ -838,6 +844,9 @@ static int utf8_table2[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};
     }
 
 
+
+static uschar * base32_chars = US"abcdefghijklmnopqrstuvwxyz234567";
+
 /*************************************************
 *           Binary chop search on a table        *
 *************************************************/
@@ -3041,6 +3050,8 @@ switch(cond_type)
        "value \"%s\"", t);
       return NULL;
       }
+    DEBUG(D_expand) debug_printf("%s: condition evaluated to %s\n", ourname,
+        boolvalue? "true":"false");
     if (yield != NULL) *yield = (boolvalue == testfor);
     return s;
     }
@@ -3182,16 +3193,17 @@ items. */
 while (isspace(*s)) s++;
 if (*s == '}')
   {
-  if (type[0] == 'i')
-    {
-    if (yes) *yieldptr = string_catn(*yieldptr, sizeptr, ptrptr, US"true", 4);
-    }
-  else
-    {
-    if (yes && lookup_value)
-      *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, lookup_value);
-    lookup_value = save_lookup;
-    }
+  if (!skipping)
+    if (type[0] == 'i')
+      {
+      if (yes) *yieldptr = string_catn(*yieldptr, sizeptr, ptrptr, US"true", 4);
+      }
+    else
+      {
+      if (yes && lookup_value)
+       *yieldptr = string_cat(*yieldptr, sizeptr, ptrptr, lookup_value);
+      lookup_value = save_lookup;
+      }
   s++;
   goto RETURN;
   }
@@ -3488,7 +3500,6 @@ Returns:       new value of string pointer
 static uschar *
 cat_file(FILE *f, uschar *yield, int *sizep, int *ptrp, uschar *eol)
 {
-int eollen = eol ? Ustrlen(eol) : 0;
 uschar buffer[1024];
 
 while (Ufgets(buffer, sizeof(buffer), f))
@@ -3496,8 +3507,8 @@ while (Ufgets(buffer, sizeof(buffer), f))
   int len = Ustrlen(buffer);
   if (eol && buffer[len-1] == '\n') len--;
   yield = string_catn(yield, sizep, ptrp, buffer, len);
-  if (buffer[len] != 0)
-    yield = string_catn(yield, sizep, ptrp, eol, eollen);
+  if (eol && buffer[len])
+    yield = string_cat(yield, sizep, ptrp, eol);
   }
 
 if (yield) yield[*ptrp] = 0;
@@ -4105,8 +4116,9 @@ while (*s != 0)
       if (next_s == NULL) goto EXPAND_FAILED;  /* message already set */
 
       DEBUG(D_expand)
-        debug_printf("condition: %.*s\n   result: %s\n", (int)(next_s - s), s,
-          cond? "true" : "false");
+        debug_printf("  condition: %.*s\n     result: %s\n",
+         (int)(next_s - s), s,
+          cond ? "true" : "false");
 
       s = next_s;
 
@@ -4952,7 +4964,10 @@ while (*s != 0)
        }
 
       if (skipping)   /* Just pretend it worked when we're skipping */
+       {
         runrc = 0;
+       lookup_value = NULL;
+       }
       else
         {
         if (!transport_set_up_command(&argv,    /* anchor for arg list */
@@ -4994,9 +5009,9 @@ while (*s != 0)
         return code for serious disasters. Simple non-zero returns are passed on.
         */
 
-        if (sigalrm_seen == TRUE || (runrc = child_close(pid, 30)) < 0)
+        if (sigalrm_seen || (runrc = child_close(pid, 30)) < 0)
           {
-          if (sigalrm_seen == TRUE || runrc == -256)
+          if (sigalrm_seen || runrc == -256)
             {
             expand_string_message = string_sprintf("command timed out");
             killpg(pid, SIGKILL);       /* Kill the whole process group */
@@ -5166,79 +5181,81 @@ while (*s != 0)
         case 3: goto EXPAND_FAILED;
         }
 
-      if (Ustrcmp(sub[0], "md5") == 0)
-        {
-        type = HMAC_MD5;
-        use_base = &md5_base;
-        hashlen = 16;
-        hashblocklen = 64;
-        }
-      else if (Ustrcmp(sub[0], "sha1") == 0)
-        {
-        type = HMAC_SHA1;
-        use_base = &sha1_ctx;
-        hashlen = 20;
-        hashblocklen = 64;
-        }
-      else
-        {
-        expand_string_message =
-          string_sprintf("hmac algorithm \"%s\" is not recognised", sub[0]);
-        goto EXPAND_FAILED;
-        }
+      if (!skipping)
+       {
+       if (Ustrcmp(sub[0], "md5") == 0)
+         {
+         type = HMAC_MD5;
+         use_base = &md5_base;
+         hashlen = 16;
+         hashblocklen = 64;
+         }
+       else if (Ustrcmp(sub[0], "sha1") == 0)
+         {
+         type = HMAC_SHA1;
+         use_base = &sha1_ctx;
+         hashlen = 20;
+         hashblocklen = 64;
+         }
+       else
+         {
+         expand_string_message =
+           string_sprintf("hmac algorithm \"%s\" is not recognised", sub[0]);
+         goto EXPAND_FAILED;
+         }
 
-      keyptr = sub[1];
-      keylen = Ustrlen(keyptr);
+       keyptr = sub[1];
+       keylen = Ustrlen(keyptr);
 
-      /* If the key is longer than the hash block length, then hash the key
-      first */
+       /* If the key is longer than the hash block length, then hash the key
+       first */
 
-      if (keylen > hashblocklen)
-        {
-        chash_start(type, use_base);
-        chash_end(type, use_base, keyptr, keylen, keyhash);
-        keyptr = keyhash;
-        keylen = hashlen;
-        }
+       if (keylen > hashblocklen)
+         {
+         chash_start(type, use_base);
+         chash_end(type, use_base, keyptr, keylen, keyhash);
+         keyptr = keyhash;
+         keylen = hashlen;
+         }
 
-      /* Now make the inner and outer key values */
+       /* Now make the inner and outer key values */
 
-      memset(innerkey, 0x36, hashblocklen);
-      memset(outerkey, 0x5c, hashblocklen);
+       memset(innerkey, 0x36, hashblocklen);
+       memset(outerkey, 0x5c, hashblocklen);
 
-      for (i = 0; i < keylen; i++)
-        {
-        innerkey[i] ^= keyptr[i];
-        outerkey[i] ^= keyptr[i];
-        }
+       for (i = 0; i < keylen; i++)
+         {
+         innerkey[i] ^= keyptr[i];
+         outerkey[i] ^= keyptr[i];
+         }
 
-      /* Now do the hashes */
+       /* Now do the hashes */
 
-      chash_start(type, use_base);
-      chash_mid(type, use_base, innerkey);
-      chash_end(type, use_base, sub[2], Ustrlen(sub[2]), innerhash);
+       chash_start(type, use_base);
+       chash_mid(type, use_base, innerkey);
+       chash_end(type, use_base, sub[2], Ustrlen(sub[2]), innerhash);
 
-      chash_start(type, use_base);
-      chash_mid(type, use_base, outerkey);
-      chash_end(type, use_base, innerhash, hashlen, finalhash);
+       chash_start(type, use_base);
+       chash_mid(type, use_base, outerkey);
+       chash_end(type, use_base, innerhash, hashlen, finalhash);
 
-      /* Encode the final hash as a hex string */
+       /* Encode the final hash as a hex string */
 
-      p = finalhash_hex;
-      for (i = 0; i < hashlen; i++)
-        {
-        *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
-        *p++ = hex_digits[finalhash[i] & 0x0f];
-        }
+       p = finalhash_hex;
+       for (i = 0; i < hashlen; i++)
+         {
+         *p++ = hex_digits[(finalhash[i] & 0xf0) >> 4];
+         *p++ = hex_digits[finalhash[i] & 0x0f];
+         }
 
-      DEBUG(D_any) debug_printf("HMAC[%s](%.*s,%.*s)=%.*s\n", sub[0],
-        (int)keylen, keyptr, Ustrlen(sub[2]), sub[2], hashlen*2, finalhash_hex);
+       DEBUG(D_any) debug_printf("HMAC[%s](%.*s,%s)=%.*s\n",
+         sub[0], (int)keylen, keyptr, sub[2], hashlen*2, finalhash_hex);
 
-      yield = string_catn(yield, &size, &ptr, finalhash_hex, hashlen*2);
+       yield = string_catn(yield, &size, &ptr, finalhash_hex, hashlen*2);
+       }
+      continue;
       }
 
-    continue;
-
     /* Handle global substitution for "sg" - like Perl's s/xxx/yyy/g operator.
     We have to save the numerical variables and restore them afterwards. */
 
@@ -6256,6 +6273,47 @@ while (*s != 0)
 
     switch(c)
       {
+      case EOP_BASE32:
+       {
+        uschar *t;
+        unsigned long int n = Ustrtoul(sub, &t, 10);
+       uschar * s = NULL;
+       int sz = 0, i = 0;
+
+        if (*t != 0)
+          {
+          expand_string_message = string_sprintf("argument for base32 "
+            "operator is \"%s\", which is not a decimal number", sub);
+          goto EXPAND_FAILED;
+          }
+       for ( ; n; n >>= 5)
+         s = string_catn(s, &sz, &i, &base32_chars[n & 0x1f], 1);
+
+       while (i > 0) yield = string_catn(yield, &size, &ptr, &s[--i], 1);
+       continue;
+       }
+
+      case EOP_BASE32D:
+        {
+        uschar *tt = sub;
+        unsigned long int n = 0;
+       uschar * s;
+        while (*tt)
+          {
+          uschar * t = Ustrchr(base32_chars, *tt++);
+          if (t == NULL)
+            {
+            expand_string_message = string_sprintf("argument for base32d "
+              "operator is \"%s\", which is not a base 32 number", sub);
+            goto EXPAND_FAILED;
+            }
+          n = n * 32 + (t - base32_chars);
+          }
+        s = string_sprintf("%ld", n);
+        yield = string_cat(yield, &size, &ptr, s);
+        continue;
+        }
+
       case EOP_BASE62:
         {
         uschar *t;
@@ -7055,11 +7113,23 @@ while (*s != 0)
 
       case EOP_ESCAPE:
         {
-        const uschar *t = string_printing(sub);
+        const uschar * t = string_printing(sub);
         yield = string_cat(yield, &size, &ptr, t);
         continue;
         }
 
+      case EOP_ESCAPE8BIT:
+       {
+       const uschar * s = sub;
+       uschar c;
+
+       for (s = sub; (c = *s); s++)
+         yield = c < 127 && c != '\\'
+           ? string_catn(yield, &size, &ptr, s, 1)
+           : string_catn(yield, &size, &ptr, string_sprintf("\\%03o", c), 4);
+       continue;
+       }
+
       /* Handle numeric expression evaluation */
 
       case EOP_EVAL:
@@ -7357,8 +7427,7 @@ while (*s != 0)
       yield = NULL;
       size = 0;
       }
-    value = find_variable(name, FALSE, skipping, &newsize);
-    if (value == NULL)
+    if (!(value = find_variable(name, FALSE, skipping, &newsize)))
       {
       expand_string_message =
         string_sprintf("unknown variable in \"${%s}\"", name);
@@ -7366,13 +7435,14 @@ while (*s != 0)
       goto EXPAND_FAILED;
       }
     len = Ustrlen(value);
-    if (yield == NULL && newsize != 0)
+    if (!yield && newsize)
       {
       yield = value;
       size = newsize;
       ptr = len;
       }
-    else yield = string_catn(yield, &size, &ptr, value, len);
+    else
+      yield = string_catn(yield, &size, &ptr, value, len);
     continue;
     }