Hurd: errno really uses more than a short-sized value. Bug 2476
[exim.git] / src / src / imap_utf7.c
index 10cc1f7fa15dc29de644ea860e15e98cf112271c..aac0fef6a04e1fffe84e6ff6620a2b46ef867819 100644 (file)
@@ -1,6 +1,9 @@
+/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* See the file NOTICE for conditions of use and distribution. */
+
 #include "exim.h"
 
-#ifdef EXPERIMENTAL_INTERNATIONAL
+#ifdef SUPPORT_I18N
 
 uschar *
 imap_utf7_encode(uschar *string, const uschar *charset, uschar sep,
@@ -8,12 +11,11 @@ imap_utf7_encode(uschar *string, const uschar *charset, uschar sep,
 {
 static uschar encode_base64[64] =
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
-int ptr = 0;
-int size = 0;
 size_t slen;
-uschar *sptr, *yield = NULL;
-int i, j;
-uschar c;
+uschar *sptr;
+gstring * yield = NULL;
+int i = 0;     /* compiler quietening */
+uschar c = 0;  /* compiler quietening */
 BOOL base64mode = FALSE;
 BOOL lastsep = FALSE;
 uschar utf16buf[256];
@@ -25,7 +27,7 @@ uschar *outptr = outbuf;
 iconv_t icd;
 #endif
 
-if (!specials) specials = "";
+if (!specials) specials = US"";
 
 /* Pass over the string. If it consists entirely of "normal" characters
    (possibly with leading seps), return it as is. */
@@ -37,7 +39,7 @@ for (s = string; *s; s++)
      || *s < 0x20
      || strchr("./&", *s)
      || *s == sep
-     || strchr(specials, *s)
+     || Ustrchr(specials, *s)
      )
     break;
   }
@@ -49,7 +51,7 @@ sptr = string;
 slen = Ustrlen(string);
 
 #if HAVE_ICONV
-if ((icd = iconv_open(US"UTF-16BE", charset)) == (iconv_t)-1)
+if ((icd = iconv_open("UTF-16BE", CCS charset)) == (iconv_t)-1)
   {
   *error = string_sprintf(
        "imapfolder: iconv_open(\"UTF-16BE\", \"%s\") failed: %s%s",
@@ -57,7 +59,7 @@ if ((icd = iconv_open(US"UTF-16BE", charset)) == (iconv_t)-1)
     errno == EINVAL ? " (maybe unsupported conversion)" : "");
   return NULL;
   }
-#endif  
+#endif
 
 while (slen > 0)
   {
@@ -76,7 +78,7 @@ while (slen > 0)
     return NULL;
     }
 #else
-  for (utf16ptr = utf16buf; 
+  for (utf16ptr = utf16buf;
        slen > 0 && (utf16ptr - utf16buf) < sizeof(utf16buf);
        utf16ptr += 2, slen--, sptr++)
     {
@@ -92,19 +94,19 @@ while (slen > 0)
     if (  s[0] != 0
        || s[1] >= 0x7f
        || s[1] < 0x20
-       || (strchr(specials, s[1]) && s[1] != sep)
+       || (Ustrchr(specials, s[1]) && s[1] != sep)
        )
       {
       lastsep = FALSE;
       /* Encode as modified BASE64 */
-      if (!base64mode) 
+      if (!base64mode)
         {
         *outptr++ = '&';
         base64mode = TRUE;
         i = 0;
         }
 
-      for (j = 0; j < 2; j++, s++) switch (i++) 
+      for (int j = 0; j < 2; j++, s++) switch (i++)
        {
        case 0:
          /* Top 6 bits of the first octet */
@@ -130,7 +132,7 @@ while (slen > 0)
       /* Encode as self (almost) */
       if (base64mode)
         {
-        switch (i) 
+        switch (i)
           {
           case 1:
                /* Remaining bottom 2 bits of the last octet */
@@ -165,22 +167,21 @@ while (slen > 0)
     else
       {
       *error = string_sprintf("imapfolder: illegal character '%c'", s[1]);
-      if (yield) store_reset(yield);
       return NULL;
       }
 
     if (outptr > outbuf + sizeof(outbuf) - 3)
       {
-      yield = string_cat(yield, &size, &ptr, outbuf, outptr - outbuf);
+      yield = string_catn(yield, outbuf, outptr - outbuf);
       outptr = outbuf;
       }
 
     }
-  } /* End of input string */  
+  } /* End of input string */
 
-if (base64mode) 
+if (base64mode)
   {
-  switch (i) 
+  switch (i)
     {
     case 1:
       /* Remaining bottom 2 bits of the last octet */
@@ -197,12 +198,12 @@ if (base64mode)
 iconv_close(icd);
 #endif
 
-yield = string_cat(yield, &size, &ptr, outbuf, outptr - outbuf);
-if (yield[ptr-1] == '.')
-  ptr--;
-yield[ptr] = '\0';
+yield = string_catn(yield, outbuf, outptr - outbuf);
+
+if (yield->s[yield->ptr-1] == '.')
+  yield->ptr--;
 
-return yield;
+return string_from_gstring(yield);
 }
 
 #endif /* whole file */