/* * XXX:This conversion might not be fully MS-Compatible * for calculating hashes. The output length may differ * for some locales and needs to be handled from where * the call is made. */ int smb_toupper(const char *inbuf, char *outbuf, size_t outlen) { int err = 0; size_t inlen, inrem, outrem; inrem = inlen = strlen(inbuf); outrem = outlen; (void) u8_textprep_str((char *)inbuf, &inrem, outbuf, &outrem, U8_TEXTPREP_TOUPPER, U8_UNICODE_LATEST, &err); /* inrem, outrem are bytes unused, remaining */ if (inrem) { SMBSDEBUG("input %d remains: %s\n", (int)inrem, inbuf); inlen -= inrem; } if (outrem) { outlen -= outrem; outbuf[outlen] = '\0'; } if (outlen > inlen) { SMBSDEBUG("outlen > inlen! (%d > %d)\n", (int)outlen, (int)inlen); /* Truncate to inlen here? */ } return (err); }
/* * A simple wrapper around u8_textprep_str() that returns the Unicode * upper-case version of some string. Returns memory from malloc. * Borrowed from idmapd. */ static char * utf8_str_to_upper_or_lower(const char *s, int upper_lower) { char *res = NULL; char *outs; size_t inlen, outlen, inbleft, outbleft; int rc, err; /* * u8_textprep_str() does not allocate memory. The input and * output buffers may differ in size (though that would be more * likely when normalization is done). We have to loop over it... * * To improve the chances that we can avoid looping we add 10 * bytes of output buffer room the first go around. */ inlen = inbleft = strlen(s); outlen = outbleft = inlen + 10; if ((res = malloc(outlen)) == NULL) return (NULL); outs = res; while ((rc = u8_textprep_str((char *)s, &inbleft, outs, &outbleft, upper_lower, U8_UNICODE_LATEST, &err)) < 0 && err == E2BIG) { if ((res = realloc(res, outlen + inbleft)) == NULL) return (NULL); /* adjust input/output buffer pointers */ s += (inlen - inbleft); outs = res + outlen - outbleft; /* adjust outbleft and outlen */ outlen += inbleft; outbleft += inbleft; } if (rc < 0) { free(res); res = NULL; return (NULL); } res[outlen - outbleft] = '\0'; return (res); }