xref: /freebsd/contrib/smbfs/lib/smb/nls.c (revision ce102ac2aed8def521f53e59c070ec011dd202c7)
1f1b9d127SSheldon Hearn /*
2f1b9d127SSheldon Hearn  * Copyright (c) 2000-2001, Boris Popov
3f1b9d127SSheldon Hearn  * All rights reserved.
4f1b9d127SSheldon Hearn  *
5f1b9d127SSheldon Hearn  * Redistribution and use in source and binary forms, with or without
6f1b9d127SSheldon Hearn  * modification, are permitted provided that the following conditions
7f1b9d127SSheldon Hearn  * are met:
8f1b9d127SSheldon Hearn  * 1. Redistributions of source code must retain the above copyright
9f1b9d127SSheldon Hearn  *    notice, this list of conditions and the following disclaimer.
10f1b9d127SSheldon Hearn  * 2. Redistributions in binary form must reproduce the above copyright
11f1b9d127SSheldon Hearn  *    notice, this list of conditions and the following disclaimer in the
12f1b9d127SSheldon Hearn  *    documentation and/or other materials provided with the distribution.
13f1b9d127SSheldon Hearn  * 3. All advertising materials mentioning features or use of this software
14f1b9d127SSheldon Hearn  *    must display the following acknowledgement:
15f1b9d127SSheldon Hearn  *    This product includes software developed by Boris Popov.
16f1b9d127SSheldon Hearn  * 4. Neither the name of the author nor the names of any co-contributors
17f1b9d127SSheldon Hearn  *    may be used to endorse or promote products derived from this software
18f1b9d127SSheldon Hearn  *    without specific prior written permission.
19f1b9d127SSheldon Hearn  *
20f1b9d127SSheldon Hearn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21f1b9d127SSheldon Hearn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22f1b9d127SSheldon Hearn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23f1b9d127SSheldon Hearn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24f1b9d127SSheldon Hearn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25f1b9d127SSheldon Hearn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26f1b9d127SSheldon Hearn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27f1b9d127SSheldon Hearn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28f1b9d127SSheldon Hearn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29f1b9d127SSheldon Hearn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30f1b9d127SSheldon Hearn  * SUCH DAMAGE.
31f1b9d127SSheldon Hearn  *
32b4bd78b0SBoris Popov  * $Id: nls.c,v 1.10 2002/07/22 08:33:59 bp Exp $
33f1b9d127SSheldon Hearn  */
34f1b9d127SSheldon Hearn 
35caef65b8SDavid E. O'Brien #include <sys/cdefs.h>
36caef65b8SDavid E. O'Brien __FBSDID("$FreeBSD$");
37caef65b8SDavid E. O'Brien 
38f1b9d127SSheldon Hearn #include <sys/types.h>
39f1b9d127SSheldon Hearn #include <sys/sysctl.h>
40f1b9d127SSheldon Hearn #include <ctype.h>
41f1b9d127SSheldon Hearn #include <errno.h>
42f1b9d127SSheldon Hearn #include <stdio.h>
43caef65b8SDavid E. O'Brien #include <string.h>
44f1b9d127SSheldon Hearn #include <stdlib.h>
45f1b9d127SSheldon Hearn #include <locale.h>
46f1b9d127SSheldon Hearn #include <err.h>
47f1b9d127SSheldon Hearn #include <netsmb/smb_lib.h>
48f1b9d127SSheldon Hearn 
49*ce102ac2SGleb Smirnoff #ifdef HAVE_ICONV
50*ce102ac2SGleb Smirnoff #include <iconv.h>
51*ce102ac2SGleb Smirnoff #endif
52*ce102ac2SGleb Smirnoff 
53f1b9d127SSheldon Hearn u_char nls_lower[256];
54f1b9d127SSheldon Hearn u_char nls_upper[256];
55f1b9d127SSheldon Hearn 
56*ce102ac2SGleb Smirnoff #ifdef HAVE_ICONV
57f1b9d127SSheldon Hearn static iconv_t nls_toext, nls_toloc;
58*ce102ac2SGleb Smirnoff #endif
59f1b9d127SSheldon Hearn 
60f1b9d127SSheldon Hearn int
61f1b9d127SSheldon Hearn nls_setlocale(const char *name)
62f1b9d127SSheldon Hearn {
63f1b9d127SSheldon Hearn 	int i;
64f1b9d127SSheldon Hearn 
65f1b9d127SSheldon Hearn 	if (setlocale(LC_CTYPE, name) == NULL) {
66f1b9d127SSheldon Hearn 		warnx("can't set locale '%s'\n", name);
67f1b9d127SSheldon Hearn 		return EINVAL;
68f1b9d127SSheldon Hearn 	}
69f1b9d127SSheldon Hearn 	for (i = 0; i < 256; i++) {
70f1b9d127SSheldon Hearn 		nls_lower[i] = tolower(i);
71f1b9d127SSheldon Hearn 		nls_upper[i] = toupper(i);
72f1b9d127SSheldon Hearn 	}
73f1b9d127SSheldon Hearn 	return 0;
74f1b9d127SSheldon Hearn }
75f1b9d127SSheldon Hearn 
76f1b9d127SSheldon Hearn int
77f1b9d127SSheldon Hearn nls_setrecode(const char *local, const char *external)
78f1b9d127SSheldon Hearn {
79*ce102ac2SGleb Smirnoff #ifdef HAVE_ICONV
80f1b9d127SSheldon Hearn 	iconv_t icd;
81f1b9d127SSheldon Hearn 
82f1b9d127SSheldon Hearn 	if (nls_toext)
8309601309SGleb Smirnoff 		iconv_close(nls_toext);
84f1b9d127SSheldon Hearn 	if (nls_toloc)
8509601309SGleb Smirnoff 		iconv_close(nls_toloc);
86f1b9d127SSheldon Hearn 	nls_toext = nls_toloc = (iconv_t)0;
8709601309SGleb Smirnoff 	icd = iconv_open(external, local);
88f1b9d127SSheldon Hearn 	if (icd == (iconv_t)-1)
89f1b9d127SSheldon Hearn 		return errno;
90f1b9d127SSheldon Hearn 	nls_toext = icd;
9109601309SGleb Smirnoff 	icd = iconv_open(local, external);
92f1b9d127SSheldon Hearn 	if (icd == (iconv_t)-1) {
9309601309SGleb Smirnoff 		iconv_close(nls_toext);
94f1b9d127SSheldon Hearn 		nls_toext = (iconv_t)0;
95f1b9d127SSheldon Hearn 		return errno;
96f1b9d127SSheldon Hearn 	}
97f1b9d127SSheldon Hearn 	nls_toloc = icd;
98f1b9d127SSheldon Hearn 	return 0;
99*ce102ac2SGleb Smirnoff #else
100*ce102ac2SGleb Smirnoff 	return ENOENT;
101df3342d6SSheldon Hearn #endif
102f1b9d127SSheldon Hearn }
103f1b9d127SSheldon Hearn 
104f1b9d127SSheldon Hearn char *
105f1b9d127SSheldon Hearn nls_str_toloc(char *dst, const char *src)
106f1b9d127SSheldon Hearn {
107*ce102ac2SGleb Smirnoff #ifdef HAVE_ICONV
108f1b9d127SSheldon Hearn 	char *p = dst;
109caef65b8SDavid E. O'Brien 	size_t inlen, outlen;
110f1b9d127SSheldon Hearn 
111f1b9d127SSheldon Hearn 	if (nls_toloc == (iconv_t)0)
112f1b9d127SSheldon Hearn 		return strcpy(dst, src);
113f1b9d127SSheldon Hearn 	inlen = outlen = strlen(src);
11409601309SGleb Smirnoff 	iconv(nls_toloc, NULL, NULL, &p, &outlen);
11509601309SGleb Smirnoff 	while (iconv(nls_toloc, &src, &inlen, &p, &outlen) == -1) {
116b4bd78b0SBoris Popov 		*p++ = *src++;
117b4bd78b0SBoris Popov 		inlen--;
118b4bd78b0SBoris Popov 		outlen--;
119b4bd78b0SBoris Popov 	}
120f1b9d127SSheldon Hearn 	*p = 0;
121f1b9d127SSheldon Hearn 	return dst;
122*ce102ac2SGleb Smirnoff #else
123*ce102ac2SGleb Smirnoff 	return strcpy(dst, src);
124*ce102ac2SGleb Smirnoff #endif
125f1b9d127SSheldon Hearn }
126f1b9d127SSheldon Hearn 
127f1b9d127SSheldon Hearn char *
128f1b9d127SSheldon Hearn nls_str_toext(char *dst, const char *src)
129f1b9d127SSheldon Hearn {
130*ce102ac2SGleb Smirnoff #ifdef HAVE_ICONV
131f1b9d127SSheldon Hearn 	char *p = dst;
132caef65b8SDavid E. O'Brien 	size_t inlen, outlen;
133f1b9d127SSheldon Hearn 
134f1b9d127SSheldon Hearn 	if (nls_toext == (iconv_t)0)
135f1b9d127SSheldon Hearn 		return strcpy(dst, src);
136f1b9d127SSheldon Hearn 	inlen = outlen = strlen(src);
13709601309SGleb Smirnoff 	iconv(nls_toext, NULL, NULL, &p, &outlen);
13809601309SGleb Smirnoff 	while (iconv(nls_toext, &src, &inlen, &p, &outlen) == -1) {
139b4bd78b0SBoris Popov 		*p++ = *src++;
140b4bd78b0SBoris Popov 		inlen--;
141b4bd78b0SBoris Popov 		outlen--;
142b4bd78b0SBoris Popov 	}
143f1b9d127SSheldon Hearn 	*p = 0;
144f1b9d127SSheldon Hearn 	return dst;
145*ce102ac2SGleb Smirnoff #else
146*ce102ac2SGleb Smirnoff 	return strcpy(dst, src);
147*ce102ac2SGleb Smirnoff #endif
148f1b9d127SSheldon Hearn }
149f1b9d127SSheldon Hearn 
150f1b9d127SSheldon Hearn void *
151f1b9d127SSheldon Hearn nls_mem_toloc(void *dst, const void *src, int size)
152f1b9d127SSheldon Hearn {
153*ce102ac2SGleb Smirnoff #ifdef HAVE_ICONV
154f1b9d127SSheldon Hearn 	char *p = dst;
155f1b9d127SSheldon Hearn 	const char *s = src;
156caef65b8SDavid E. O'Brien 	size_t inlen, outlen;
157f1b9d127SSheldon Hearn 
158f1b9d127SSheldon Hearn 	if (size == 0)
159f1b9d127SSheldon Hearn 		return NULL;
160f1b9d127SSheldon Hearn 
161f1b9d127SSheldon Hearn 	if (nls_toloc == (iconv_t)0)
162f1b9d127SSheldon Hearn 		return memcpy(dst, src, size);
163f1b9d127SSheldon Hearn 	inlen = outlen = size;
16409601309SGleb Smirnoff 	iconv(nls_toloc, NULL, NULL, &p, &outlen);
16509601309SGleb Smirnoff 	while (iconv(nls_toloc, &s, &inlen, &p, &outlen) == -1) {
166b4bd78b0SBoris Popov 		*p++ = *s++;
167b4bd78b0SBoris Popov 		inlen--;
168b4bd78b0SBoris Popov 		outlen--;
169b4bd78b0SBoris Popov 	}
170f1b9d127SSheldon Hearn 	return dst;
171*ce102ac2SGleb Smirnoff #else
172*ce102ac2SGleb Smirnoff 	return memcpy(dst, src, size);
173*ce102ac2SGleb Smirnoff #endif
174f1b9d127SSheldon Hearn }
175f1b9d127SSheldon Hearn 
176f1b9d127SSheldon Hearn void *
177f1b9d127SSheldon Hearn nls_mem_toext(void *dst, const void *src, int size)
178f1b9d127SSheldon Hearn {
179*ce102ac2SGleb Smirnoff #ifdef HAVE_ICONV
180f1b9d127SSheldon Hearn 	char *p = dst;
181f1b9d127SSheldon Hearn 	const char *s = src;
182caef65b8SDavid E. O'Brien 	size_t inlen, outlen;
183f1b9d127SSheldon Hearn 
184f1b9d127SSheldon Hearn 	if (size == 0)
185f1b9d127SSheldon Hearn 		return NULL;
186f1b9d127SSheldon Hearn 
18709601309SGleb Smirnoff 	if (nls_toext == (iconv_t)0)
188f1b9d127SSheldon Hearn 		return memcpy(dst, src, size);
189f1b9d127SSheldon Hearn 
190f1b9d127SSheldon Hearn 	inlen = outlen = size;
19109601309SGleb Smirnoff 	iconv(nls_toext, NULL, NULL, &p, &outlen);
19209601309SGleb Smirnoff 	while (iconv(nls_toext, &s, &inlen, &p, &outlen) == -1) {
193b4bd78b0SBoris Popov 		*p++ = *s++;
194b4bd78b0SBoris Popov 		inlen--;
195b4bd78b0SBoris Popov 		outlen--;
196b4bd78b0SBoris Popov 	}
197f1b9d127SSheldon Hearn 	return dst;
198*ce102ac2SGleb Smirnoff #else
199*ce102ac2SGleb Smirnoff 	return memcpy(dst, src, size);
200*ce102ac2SGleb Smirnoff #endif
201f1b9d127SSheldon Hearn }
202f1b9d127SSheldon Hearn 
203f1b9d127SSheldon Hearn char *
204f1b9d127SSheldon Hearn nls_str_upper(char *dst, const char *src)
205f1b9d127SSheldon Hearn {
206f1b9d127SSheldon Hearn 	char *p = dst;
207f1b9d127SSheldon Hearn 
208f1b9d127SSheldon Hearn 	while (*src)
209f1b9d127SSheldon Hearn 		*dst++ = toupper(*src++);
210f1b9d127SSheldon Hearn 	*dst = 0;
211f1b9d127SSheldon Hearn 	return p;
212f1b9d127SSheldon Hearn }
213f1b9d127SSheldon Hearn 
214f1b9d127SSheldon Hearn char *
215f1b9d127SSheldon Hearn nls_str_lower(char *dst, const char *src)
216f1b9d127SSheldon Hearn {
217f1b9d127SSheldon Hearn 	char *p = dst;
218f1b9d127SSheldon Hearn 
219f1b9d127SSheldon Hearn 	while (*src)
220f1b9d127SSheldon Hearn 		*dst++ = tolower(*src++);
221f1b9d127SSheldon Hearn 	*dst = 0;
222f1b9d127SSheldon Hearn 	return p;
223f1b9d127SSheldon Hearn }
224