I18N: new ${imapfolder_<sep>:<string>} expansion item. Bug 420
[exim.git] / src / src / expand.c
index 145b827dc5c157e128904aba4d05fc6c93134b9a..2092701630b254008d68dfdef81dd869ebd6f131 100644 (file)
@@ -114,6 +114,9 @@ static uschar *item_table[] = {
   US"hash",
   US"hmac",
   US"if",
+#ifdef EXPERIMENTAL_INTERNATIONAL
+  US"imapfolder",
+#endif
   US"length",
   US"listextract",
   US"lookup",
@@ -140,6 +143,9 @@ enum {
   EITEM_HASH,
   EITEM_HMAC,
   EITEM_IF,
+#ifdef EXPERIMENTAL_INTERNATIONAL
+  EITEM_IMAPFOLDER,
+#endif
   EITEM_LENGTH,
   EITEM_LISTEXTRACT,
   EITEM_LOOKUP,
@@ -168,7 +174,14 @@ static uschar *op_table_underscore[] = {
   US"quote_local_part",
   US"reverse_ip",
   US"time_eval",
-  US"time_interval"};
+  US"time_interval"
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ ,US"utf8_domain_from_alabel",
+  US"utf8_domain_to_alabel",
+  US"utf8_localpart_from_alabel",
+  US"utf8_localpart_to_alabel"
+#endif
+  };
 
 enum {
   EOP_FROM_UTF8,
@@ -176,7 +189,14 @@ enum {
   EOP_QUOTE_LOCAL_PART,
   EOP_REVERSE_IP,
   EOP_TIME_EVAL,
-  EOP_TIME_INTERVAL };
+  EOP_TIME_INTERVAL
+#ifdef EXPERIMENTAL_INTERNATIONAL
+ ,EOP_UTF8_DOMAIN_FROM_ALABEL,
+  EOP_UTF8_DOMAIN_TO_ALABEL,
+  EOP_UTF8_LOCALPART_FROM_ALABEL,
+  EOP_UTF8_LOCALPART_TO_ALABEL
+#endif
+  };
 
 static uschar *op_table_main[] = {
   US"address",
@@ -549,6 +569,9 @@ static var_entry var_table[] = {
   { "message_id",          vtype_stringptr,   &message_id },
   { "message_linecount",   vtype_int,         &message_linecount },
   { "message_size",        vtype_int,         &message_size },
+#ifdef EXPERIMENTAL_INTERNATIONAL
+  { "message_smtputf8",    vtype_bool,        &message_smtputf8 },
+#endif
 #ifdef WITH_CONTENT_SCAN
   { "mime_anomaly_level",  vtype_int,         &mime_anomaly_level },
   { "mime_anomaly_text",   vtype_stringptr,   &mime_anomaly_text },
@@ -4053,6 +4076,45 @@ while (*s != 0)
       continue;
       }
 
+#ifdef EXPERIMENTAL_INTERNATIONAL
+    case EITEM_IMAPFOLDER:
+      {                                /* ${imapfolder {name}{sep]{specials}} */
+      uschar *sub_arg[3];
+      uschar *encoded;
+
+      switch(read_subs(sub_arg, 3, 1, &s, skipping, TRUE, name, &resetok))
+        {
+        case 1: goto EXPAND_FAILED_CURLY;
+        case 2:
+        case 3: goto EXPAND_FAILED;
+        }
+
+      if (sub_arg[1] == NULL)          /* One argument */
+       {
+       sub_arg[1] = "/";               /* default separator */
+       sub_arg[2] = NULL;
+       }
+      else if (sub_arg[2] == NULL)     /* Two arguments */
+       sub_arg[2] = NULL;
+
+      if (Ustrlen(sub_arg[1]) != 1)
+       {
+       expand_string_message = 
+         string_sprintf(
+               "IMAP folder separator must be one character, found \"%s\"", 
+               sub_arg[1]);
+       goto EXPAND_FAILED;
+       }
+
+      if (!(encoded = imap_utf7_encode(sub_arg[0], headers_charset,
+                         sub_arg[1][0], sub_arg[2], &expand_string_message)))
+       goto EXPAND_FAILED;
+      if (!skipping)
+       yield = string_cat(yield, &size, &ptr, encoded, Ustrlen(encoded));
+      continue;
+      }
+#endif
+
     /* Handle database lookups unless locked out. If "skipping" is TRUE, we are
     expanding an internal string that isn't actually going to be used. All we
     need to do is check the syntax, so don't do a lookup at all. Preserve the
@@ -5501,7 +5563,7 @@ while (*s != 0)
         while (isspace(*s)) s++;
         if (*s++ != '{') goto EXPAND_FAILED_CURLY;
         t = expand_string_internal(s, TRUE, &s, skipping, TRUE, &resetok);
-        if (temp == NULL) goto EXPAND_FAILED;
+        if (!t) goto EXPAND_FAILED;
         lookup_value = t;
         if (*s++ != '}') goto EXPAND_FAILED_CURLY;
         }
@@ -6552,16 +6614,13 @@ while (*s != 0)
          if (bytes_left)
            {
            if ((c & 0xc0) != 0x80)
-             {
                    /* wrong continuation byte; invalidate all bytes */
              complete = 1; /* error */
-             }
            else
              {
              codepoint = (codepoint << 6) | (c & 0x3f);
              seq_buff[index++] = c;
              if (--bytes_left == 0)            /* codepoint complete */
-               {
                if(codepoint > 0x10FFFF)        /* is it too large? */
                  complete = -1;        /* error (RFC3629 limit) */
                else
@@ -6569,7 +6628,6 @@ while (*s != 0)
                  yield = string_cat(yield, &size, &ptr, seq_buff, seq_len);
                  index = 0;
                  }
-               }
              }
            }
          else  /* no bytes left: new sequence */
@@ -6612,13 +6670,75 @@ while (*s != 0)
            yield = string_cat(yield, &size, &ptr, UTF8_REPLACEMENT_CHAR, 1);
            }
          if ((complete == 1) && ((c & 0x80) == 0))
-           { /* ASCII character follows incomplete sequence */
+                       /* ASCII character follows incomplete sequence */
              yield = string_cat(yield, &size, &ptr, &c, 1);
-           }
          }
         continue;
         }
 
+#ifdef EXPERIMENTAL_INTERNATIONAL
+      case EOP_UTF8_DOMAIN_TO_ALABEL:
+       {
+        uschar * error = NULL;
+       uschar * s = string_domain_utf8_to_alabel(sub, &error);
+       if (error)
+         {
+         expand_string_message = string_sprintf(
+           "error converting utf8 (%s) to alabel: %s",
+           string_printing(sub), error);
+         goto EXPAND_FAILED;
+         }
+       yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+        continue;
+       }
+
+      case EOP_UTF8_DOMAIN_FROM_ALABEL:
+       {
+        uschar * error = NULL;
+       uschar * s = string_domain_alabel_to_utf8(sub, &error);
+       if (error)
+         {
+         expand_string_message = string_sprintf(
+           "error converting alabel (%s) to utf8: %s",
+           string_printing(sub), error);
+         goto EXPAND_FAILED;
+         }
+       yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+        continue;
+       }
+
+      case EOP_UTF8_LOCALPART_TO_ALABEL:
+       {
+        uschar * error = NULL;
+       uschar * s = string_localpart_utf8_to_alabel(sub, &error);
+       if (error)
+         {
+         expand_string_message = string_sprintf(
+           "error converting utf8 (%s) to alabel: %s",
+           string_printing(sub), error);
+         goto EXPAND_FAILED;
+         }
+       yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+       DEBUG(D_expand) debug_printf("yield: '%s'\n", yield);
+        continue;
+       }
+
+      case EOP_UTF8_LOCALPART_FROM_ALABEL:
+       {
+        uschar * error = NULL;
+       uschar * s = string_localpart_alabel_to_utf8(sub, &error);
+       if (error)
+         {
+         expand_string_message = string_sprintf(
+           "error converting alabel (%s) to utf8: %s",
+           string_printing(sub), error);
+         goto EXPAND_FAILED;
+         }
+       yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
+        continue;
+       }
+#endif /* EXPERIMENTAL_INTERNATIONAL */
+
       /* escape turns all non-printing characters into escape sequences. */
 
       case EOP_ESCAPE: