/*
 * 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);
}
Beispiel #2
0
/*
 * 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);
}