2 * Copyright (c) 2020 Proofpoint, Inc. and its suppliers.
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
12 #include <sm/sendmail.h>
15 #include <sm/string.h>
18 # include <sm/ixlen.h>
19 # include <unicode/ucasemap.h>
20 # include <unicode/ustring.h>
21 # include <unicode/uchar.h>
24 ** ASCIISTR -- check whether a string is printable ASCII
30 ** TRUE iff printable ASCII
41 while ((ch = (unsigned char)*str) != '\0' && ch >= 32 && ch < 127)
48 ** MAKELOWER -- Translate a line into lower case
51 ** p -- string to translate (modified in place if possible). [A]
57 ** String p is translated to lower case if possible.
72 return (char *)sm_lowercase(p);
74 for (; (c = *p) != '\0'; p++)
75 if (isascii(c) && isupper(c))
82 ** SM_LOWERCASE -- lower case a UTF-8 string
83 ** Note: this should ONLY be applied to a UTF-8 string,
84 ** i.e., the caller should check first if it isn't an ASCII string.
87 ** str -- original string
90 ** lower case version of string [S]
92 ** How to return an error description due to failed unicode calls?
93 ** However, is that even relevant?
104 static UCaseMap *csm = NULL;
105 static char *out = NULL;
106 static int outlen = 0;
108 # if SM_CHECK_REQUIRE
109 if (sm_debug_active(&SmExpensiveRequire, 3))
110 SM_REQUIRE(!asciistr(str));
112 /* an empty string is always ASCII */
113 SM_REQUIRE(NULL != str && '\0' != *str);
117 error = U_ZERO_ERROR;
118 csm = ucasemap_open("en_US", U_FOLD_CASE_DEFAULT, &error);
119 if (U_SUCCESS(error) == 0)
121 /* syserr("ucasemap_open error: %s", u_errorName(error)); */
131 out = sm_realloc_x(out, outlen);
134 for (n = 0; n < 3; n++)
136 error = U_ZERO_ERROR;
137 req = ucasemap_utf8FoldCase(csm, out, olen, str, ilen, &error);
138 if (U_SUCCESS(error))
143 out = sm_realloc_x(out, outlen);
148 else if (error == U_BUFFER_OVERFLOW_ERROR)
151 out = sm_realloc_x(out, outlen);
156 /* syserr("conversion error for \"%s\": %s", str, u_errorName(error)); */