Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libncp / ncpl_nls.c
1 /*
2  * Copyright (c) 1999-2002, Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Boris Popov.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $FreeBSD: src/lib/libncp/ncpl_nls.c,v 1.2.2.1 2002/04/30 08:18:24 bp Exp $
33  */
34
35 /*
36  * Languages support. Currently is very primitive.
37  */
38 #include <sys/types.h>
39 #include <ctype.h>
40 #include <errno.h>
41 #include <stdio.h>
42 #include <strings.h>
43 #include <locale.h>
44
45 #include <netncp/ncp_lib.h>
46 #include <netncp/ncp_cfg.h>
47 #include <netncp/ncp_nls.h>
48
49 #ifndef NCP_NLS_DEFAULT
50 #define NCP_NLS_DEFAULT NCP_NLS_AS_IS
51 #endif
52
53 /*
54  * TODO: Make all tables dynamically loadable.
55  */
56 #ifdef NCP_NLS_KOI2CP866
57 /* Russian tables from easy-cyrillic:
58  * Copyright (C) 1993-1994 by Andrey A. Chernov, Moscow, Russia
59  */
60 static u_int8_t alt2koi8[] = {
61         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
62         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
63         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
64         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
65         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
66         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
67         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
68         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
69         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
70         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
71         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
72         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
73         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
74         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
75         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
76         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
77         0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa,
78         0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
79         0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe,
80         0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1,
81         0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda,
82         0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
83         0x90, 0x91, 0x92, 0x81, 0x87, 0xb2, 0xb4, 0xa7,
84         0xa6, 0xb5, 0xa1, 0xa8, 0xae, 0xad, 0xac, 0x83,
85         0x84, 0x89, 0x88, 0x86, 0x80, 0x8a, 0xaf, 0xb0,
86         0xab, 0xa5, 0xbb, 0xb8, 0xb1, 0xa0, 0xbe, 0xb9,
87         0xba, 0xb6, 0xb7, 0xaa, 0xa9, 0xa2, 0xa4, 0xbd,
88         0xbc, 0x85, 0x82, 0x8d, 0x8c, 0x8e, 0x8f, 0x8b,
89         0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde,
90         0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1,
91         0xb3, 0xa3, 0x99, 0x98, 0x93, 0x9b, 0x9f, 0x97,
92         0x9c, 0x95, 0x9e, 0x96, 0xbf, 0x9d, 0x94, 0x9a
93 };
94
95 static u_int8_t koi82alt[] = {
96         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
97         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
98         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
99         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
100         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
101         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
102         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
103         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
104         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
105         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
106         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
107         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
108         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
109         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
110         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
111         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
112         0xc4, 0xb3, 0xda, 0xbf, 0xc0, 0xd9, 0xc3, 0xb4, /* 0x80 */
113         0xc2, 0xc1, 0xc5, 0xdf, 0xdc, 0xdb, 0xdd, 0xde,
114         0xb0, 0xb1, 0xb2, 0xf4, 0xfe, 0xf9, 0xfb, 0xf7,
115         0xf3, 0xf2, 0xff, 0xf5, 0xf8, 0xfd, 0xfa, 0xf6,
116         0xcd, 0xba, 0xd5, 0xf1, 0xd6, 0xc9, 0xb8, 0xb7,
117         0xbb, 0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6,
118         0xc7, 0xcc, 0xb5, 0xf0, 0xb6, 0xb9, 0xd1, 0xd2,
119         0xcb, 0xcf, 0xd0, 0xca, 0xd8, 0xd7, 0xce, 0xfc,
120         0xee, 0xa0, 0xa1, 0xe6, 0xa4, 0xa5, 0xe4, 0xa3,
121         0xe5, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
122         0xaf, 0xef, 0xe0, 0xe1, 0xe2, 0xe3, 0xa6, 0xa2,
123         0xec, 0xeb, 0xa7, 0xe8, 0xed, 0xe9, 0xe7, 0xea,
124         0x9e, 0x80, 0x81, 0x96, 0x84, 0x85, 0x94, 0x83,
125         0x95, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
126         0x8f, 0x9f, 0x90, 0x91, 0x92, 0x93, 0x86, 0x82, /* 0xf0 */ 
127         0x9c, 0x9b, 0x87, 0x98, 0x9d, 0x99, 0x97, 0x9a
128 };
129
130 #endif
131
132 /*
133  * Characters mapping for codepages used in Sweden.
134  */
135 static u_int8_t se_nw2unix[] = {
136         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
137         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
138         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
139         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
140         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
141         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
142         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
143         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
144         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
145         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
146         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
147         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
148         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
149         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
150         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
151         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
152         0xe1, 0xe2, 0xf7, 0xe7, 0xE4, 0xc4, 0xE5, 0xfa, /* 0x80 */
153         0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xC4, 0xC5,
154         0xf2, 0xf3, 0xf4, 0xf5, 0xF6, 0xe8, 0xe3, 0xfe, /* 0x90 */
155         0xfb, 0xD6, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1,
156         0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, /* 0xA0 */
157         0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0,
158         0x90, 0x91, 0x92, 0x81, 0x87, 0xb2, 0xb4, 0xa7, /* 0xB0 */
159         0xa6, 0xb5, 0xa1, 0xa8, 0xae, 0xad, 0xac, 0x83,
160         0x84, 0x89, 0x88, 0x86, 0x80, 0x8a, 0xaf, 0xb0, /* 0xC0 */
161         0xab, 0xa5, 0xbb, 0xb8, 0xb1, 0xa0, 0xbe, 0xb9,
162         0xba, 0xb6, 0xb7, 0xaa, 0xa9, 0xa2, 0xa4, 0xbd, /* 0xD0 */
163         0xbc, 0x85, 0x82, 0x8d, 0x8c, 0x8e, 0x8f, 0x8b,
164         0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, /* 0xE0 */
165         0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1,
166         0xb3, 0xa3, 0x99, 0x98, 0x93, 0x9b, 0x9f, 0x97, /* 0xF0 */
167         0x9c, 0x95, 0x9e, 0x96, 0xbf, 0x9d, 0x94, 0x9a
168 };
169
170 static u_int8_t se_unix2nw[] = {
171         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */
172         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
173         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */
174         0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
175         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */
176         0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
177         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */
178         0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f,
179         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */
180         0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
181         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */
182         0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
183         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */
184         0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
185         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */
186         0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
187         0xc4, 0xb3, 0xda, 0xbf, 0xc0, 0xd9, 0xc3, 0xb4, /* 0x80 */
188         0xc2, 0xc1, 0xc5, 0xdf, 0xdc, 0xdb, 0xdd, 0xde,
189         0xb0, 0xb1, 0xb2, 0xf4, 0xfe, 0xf9, 0xfb, 0xf7, /* 0x90 */
190         0xf3, 0xf2, 0xff, 0xf5, 0xf8, 0xfd, 0xfa, 0xf6,
191         0xcd, 0xba, 0xd5, 0xf1, 0xd6, 0xc9, 0xb8, 0xb7, /* 0xA0 */
192         0xbb, 0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6,
193         0xc7, 0xcc, 0xb5, 0xf0, 0xb6, 0xb9, 0xd1, 0xd2, /* 0xB0 */
194         0xcb, 0xcf, 0xd0, 0xca, 0xd8, 0xd7, 0xce, 0xfc,
195         0xee, 0xa0, 0xa1, 0xe6, 0x8E, 0x8F, 0xe4, 0xa3, /* 0xC0 */
196         0xe5, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
197         0xaf, 0xef, 0xe0, 0xe1, 0xe2, 0xe3, 0x99, 0xa2, /* 0xD0 */
198         0xec, 0xeb, 0xa7, 0xe8, 0xed, 0xe9, 0xe7, 0xea,
199         0x9e, 0x80, 0x81, 0x96, 0x84, 0x86, 0x94, 0x83, /* 0xE0 */
200         0x95, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
201         0x8f, 0x9f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x82, /* 0xf0 */ 
202         0x9c, 0x9b, 0x87, 0x98, 0x9d, 0x99, 0x97, 0x9a
203 };
204
205
206 static u_int8_t def2lower[256];
207 static u_int8_t def2upper[256];
208
209 /*
210  * List of available charsets
211  */
212 struct ncp_nlsdesc {
213         int     scheme;
214         char    *name;
215         struct ncp_nlstables nls;
216 };
217
218 static struct ncp_nlsdesc ncp_nlslist[] = {
219         {NCP_NLS_AS_IS, NCP_NLS_AS_IS_NAME, 
220             {def2lower, def2upper, NULL, NULL, 0}
221         },
222 #ifdef NCP_NLS_KOI2CP866
223         {NCP_NLS_KOI_866, NCP_NLS_KOI_866_NAME, 
224             {def2lower, def2upper, alt2koi8, koi82alt, 0}
225         },
226 #endif
227         {NCP_NLS_SE, NCP_NLS_SE_NAME, 
228             {def2lower, def2upper, se_nw2unix, se_unix2nw, 0}
229         },
230         {NULL, 0}
231 };
232
233 struct ncp_nlstables ncp_nls;
234
235 int
236 ncp_nls_setlocale(char *name) {
237         int i;
238
239         ncp_nls.to_lower = def2lower;
240         ncp_nls.to_upper = def2upper;
241         if (setlocale(LC_CTYPE, name) == NULL) {
242                 fprintf(stderr, "Can't set locale '%s'\n", name);
243                 return EINVAL;
244         }
245         for (i = 0; i < 256; i++) {
246                 ncp_nls.to_lower[i] = tolower(i);
247                 ncp_nls.to_upper[i] = toupper(i);
248         }
249         return 0;
250 }
251
252 int
253 ncp_nls_setrecode(int scheme) {
254         struct ncp_nlsdesc *nd;
255
256         if (scheme == 0) {
257 #if NCP_NLS_DEFAULT
258                 scheme = NCP_NLS_DEFAULT;
259 #else
260                 scheme = NCP_NLS_AS_IS;
261 #endif
262         }
263         for (nd = ncp_nlslist; nd->name; nd++) {
264                 if (nd->scheme != scheme) continue;
265                 ncp_nls.u2n = nd->nls.u2n;
266                 ncp_nls.n2u = nd->nls.n2u;
267                 return ncp_nls_setlocale("");
268         }
269         fprintf(stderr, "Character conversion scheme %d was not compiled in\n", scheme);
270         return EINVAL;
271 }
272
273 int
274 ncp_nls_setrecodebyname(char *name) {
275         struct ncp_nlsdesc *nd;
276
277         for (nd = ncp_nlslist; nd->name; nd++) {
278                 if (strcmp(nd->name, name) != 0) continue;
279                 ncp_nls.u2n = nd->nls.u2n;
280                 ncp_nls.n2u = nd->nls.n2u;
281                 return 0;
282         }
283         fprintf(stderr, "Character conversion scheme %s was not compiled in\n", name);
284         return EINVAL;
285 }
286
287 char *
288 ncp_nls_str_n2u(char *dst, const char *src) {
289         char *p;
290
291         if (ncp_nls.n2u == NULL) {
292                 return strcpy(dst, src);
293         }
294         p = dst;
295         while (*src)
296                 *p++ = ncp_nls.n2u[(u_char)*(src++)];
297         *p = 0;
298         return dst;
299 }
300
301 char *
302 ncp_nls_str_u2n(char *dst, const char *src) {
303         char *p;
304
305         if (ncp_nls.u2n == NULL) {
306                 return strcpy(dst, src);
307         }
308         p = dst;
309         while (*src)
310                 *p++ = ncp_nls.u2n[(u_char)*(src++)];
311         *p = 0;
312         return dst;
313 }
314
315 char *
316 ncp_nls_mem_n2u(char *dst, const char *src, int size) {
317         char *p;
318
319         if (size == 0) return NULL;
320         if (ncp_nls.n2u == NULL) {
321                 return memcpy(dst, src, size);
322         }
323         for(p = dst; size; size--, p++)
324                 *p = ncp_nls.n2u[(u_char)*(src++)];
325         return dst;
326 }
327
328 char *
329 ncp_nls_mem_u2n(char *dst, const char *src, int size) {
330         char *p;
331
332         if (size == 0) return NULL;
333         if (ncp_nls.u2n == NULL) {
334                 return strcpy(dst, src);
335         }
336         for(p = dst; size; size--, p++)
337                 *p = ncp_nls.u2n[(u_char)*(src++)];
338         return dst;
339 }
340
341 char *
342 ncp_str_upper(char *s) {
343         char *p = s;
344         while (*s) {
345                 *s = toupper(*s);
346                 s++;
347         }
348         return p;
349 }