return bin_len;
}
+ /* The SILC_STRING_LDAP_DN is alredy UTF-8 but it may be escaped. We
+ remove the escaping and we're done. */
+ if (bin_encoding == SILC_STRING_LDAP_DN ||
+ bin_encoding == SILC_STRING_UTF8_ESCAPE) {
+ unsigned char cv;
+
+ for (i = 0; i < bin_len; i++) {
+ if (bin[i] == '\\') {
+ if (i + 1 >= bin_len)
+ return 0;
+
+ /* If escaped character is any of the following no processing is
+ needed, otherwise it is a hex value and we need to read it. */
+ cv = bin[i + 1];
+ if (cv != ',' && cv != '+' && cv != '"' && cv != '\\' && cv != '<' &&
+ cv != '>' && cv != ';' && cv != ' ' && cv != '#') {
+ unsigned int hexval;
+ if (i + 2 >= bin_len)
+ return 0;
+ if (sscanf(&bin[i + 1], "%02X", &hexval) != 1)
+ return 0;
+ if (utf8) {
+ if (enclen + 1 > utf8_size)
+ return 0;
+ utf8[enclen] = (unsigned char)hexval;
+ }
+
+ i += 2;
+ enclen++;
+ }
+ } else {
+ if (utf8) {
+ if (enclen + 1 > utf8_size)
+ return 0;
+ utf8[enclen] = bin[i];
+ }
+ enclen++;
+ }
+ }
+
+ return enclen;
+ }
+
if (bin_encoding == SILC_STRING_LOCALE) {
#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
char *fromconv, *icp, *ocp;
return 0;
charval = bin[i];
break;
- case SILC_STRING_LDAP_DN:
- /* Remove any escaping */
- if (bin[i] == '\\') {
- unsigned char cv;
- if (i + 1 >= bin_len)
- return 0;
-
- /* If escaped character is any of the following no processing is
- needed, otherwise it is a hex value and we need to read it. */
- cv = bin[++i];
- if (cv != ',' && cv != '+' && cv != '"' && cv != '\\' && cv != '<' &&
- cv != '>' && cv != ';' && cv != ' ' && cv != '#') {
- unsigned int hexval;
- if (i + 1 >= bin_len)
- return 0;
- if (sscanf(&bin[++i], "%02X", &hexval) != 1)
- return 0;
- cv = (unsigned char)hexval;
- }
-
- charval = cv;
- break;
- }
- charval = bin[i];
- break;
default:
return 0;
break;
SilcStringEncoding bin_encoding,
unsigned char *bin, SilcUInt32 bin_size)
{
- SilcUInt32 enclen = 0, i, charval;
+ SilcUInt32 enclen = 0, i, charval, bytes;
if (!utf8 || !utf8_len)
return 0;
for (i = 0; i < utf8_len; i++) {
if ((utf8[i] & 0x80) == 0x00) {
charval = utf8[i] & 0x7f;
+ bytes = 1;
} else if ((utf8[i] & 0xe0) == 0xc0) {
if (i + 1 >= utf8_len)
return 0;
charval |= utf8[i] & 0x3f;
if (charval < 0x80)
return 0;
+ bytes = 2;
} else if ((utf8[i] & 0xf0) == 0xe0) {
if (i + 2 >= utf8_len)
return 0;
charval |= utf8[i] & 0x3f;
if (charval < 0x800)
return 0;
+ bytes = 3;
} else if ((utf8[i] & 0xf8) == 0xf0) {
if (i + 3 >= utf8_len)
return 0;
charval |= utf8[i] & 0x3f;
if (charval < 0x10000)
return 0;
+ bytes = 4;
} else if ((utf8[i] & 0xfc) == 0xf8) {
if (i + 4 >= utf8_len)
return 0;
charval |= utf8[i] & 0x3f;
if (charval < 0x200000)
return 0;
+ bytes = 5;
} else if ((utf8[i] & 0xfe) == 0xfc) {
if (i + 5 >= utf8_len)
return 0;
charval |= utf8[i] & 0x3f;
if (charval < 0x4000000)
return 0;
+ bytes = 6;
} else {
return 0;
}
break;
case SILC_STRING_LDAP_DN:
{
- /* XXX multibyte handling */
- unsigned char cv = (unsigned char)charval;
+ int k;
+ unsigned char cv;
- /* If string starts with space or # escape it */
- if (!enclen && (cv == '#' || cv == ' ')) {
- if (bin) {
- if (enclen + 2 > bin_size)
- return 0;
- bin[enclen] = '\\';
- bin[enclen + 1] = cv;
+ /* Non-printable UTF-8 characters will be escaped, printable will
+ be as is. We take the bytes directly from the original data. */
+ for (k = 0; k < bytes; k++) {
+ cv = utf8[(i - (bytes - 1)) + k];
+
+ /* If string starts with space or # escape it */
+ if (!enclen && (cv == '#' || cv == ' ')) {
+ if (bin) {
+ if (enclen + 2 > bin_size)
+ return 0;
+ bin[enclen] = '\\';
+ bin[enclen + 1] = cv;
+ }
+ enclen += 2;
+ continue;
}
- enclen += 2;
- break;
- }
- /* If string ends with space escape it */
- if (i == utf8_len - 1 && cv == ' ') {
- if (bin) {
- if (enclen + 2 > bin_size)
- return 0;
- bin[enclen] = '\\';
- bin[enclen + 1] = cv;
+ /* If string ends with space escape it */
+ if (i == utf8_len - 1 && cv == ' ') {
+ if (bin) {
+ if (enclen + 2 > bin_size)
+ return 0;
+ bin[enclen] = '\\';
+ bin[enclen + 1] = cv;
+ }
+ enclen += 2;
+ continue;
}
- enclen += 2;
- break;
- }
- /* If character is any of following then escape */
- if (cv == ',' || cv == '+' || cv == '"' || cv == '\\' || cv == '<' ||
- cv == '>' || cv == ';') {
- if (bin) {
- if (enclen + 2 > bin_size)
- return 0;
- bin[enclen] = '\\';
- bin[enclen + 1] = cv;
+ /* If character is any of following then escape */
+ if (cv == ',' || cv == '+' || cv == '"' || cv == '\\' || cv == '<' ||
+ cv == '>' || cv == ';') {
+ if (bin) {
+ if (enclen + 2 > bin_size)
+ return 0;
+ bin[enclen] = '\\';
+ bin[enclen + 1] = cv;
+ }
+ enclen += 2;
+ continue;
+ }
+
+ /* If character is not printable escape it with hex character */
+ if (!isprint((int)cv)) {
+ if (bin) {
+ if (enclen + 3 > bin_size)
+ return 0;
+ bin[enclen] = '\\';
+ snprintf(bin + enclen + 1, 3, "%02X", cv);
+ }
+ enclen += 3;
+ continue;
}
- enclen += 2;
- break;
- }
- /* If character is not printable escape it with hex character */
- if (!isprint((int)cv)) {
if (bin) {
- if (enclen + 2 > bin_size)
+ if (enclen + 1 > bin_size)
return 0;
- bin[enclen] = '\\';
- snprintf(bin + enclen + 1, 3, "%02X", cv);
+ bin[enclen] = cv;
}
- enclen += 2;
- break;
+ enclen++;
}
-
- if (bin) {
- if (enclen + 1 > bin_size)
- return 0;
- bin[enclen] = cv;
- }
- enclen++;
}
break;
default:
int main(int argc, char **argv)
{
bool success = FALSE;
+ unsigned char *s1, *s3, *s4;
+ int l;
if (argc > 1 && !strcmp(argv[1], "-d")) {
silc_debug = 1;
utf8failc(27); utf8failc(28);
utf8failc(29); utf8failc(30);
+ /* LDAP DN simple test */
+ s1 = "#&?*Pekka, Riikonen, <foobar@foobar.com>\xc4\x8d ";
+ SILC_LOG_DEBUG(("s1 = %s", s1));
+
+ /* To LDAP DN */
+ l = silc_utf8_decoded_len(s1, strlen(s1), SILC_STRING_LDAP_DN);
+ if (!l)
+ goto err;
+ s3 = silc_calloc(l + 1, sizeof(*s3));
+ silc_utf8_decode(s1, strlen(s1), SILC_STRING_LDAP_DN, s3, l);
+ SILC_LOG_DEBUG(("ldapdn = %s", s3));
+
+ /* To UTF-8 */
+ l = silc_utf8_encoded_len(s3, strlen(s3), SILC_STRING_LDAP_DN);
+ if (!l)
+ goto err;
+ s4 = silc_calloc(l + 1, sizeof(*s4));
+ silc_utf8_encode(s3, strlen(s3), SILC_STRING_LDAP_DN, s4, l);
+ SILC_LOG_DEBUG(("utf8 = %s", s4));
+
+ if (memcmp(s4, s1, strlen(s4))) {
+ SILC_LOG_DEBUG(("UTF-8 mismatch"));
+ goto err;
+ }
+
+ silc_free(s3);
+ silc_free(s4);
+
success = TRUE;
err: