1 : /*
2 : * Copyright (c) 2000,2001,2002 Japan Network Information Center.
3 : * All rights reserved.
4 : *
5 : * By using this file, you agree to the terms and conditions set forth bellow.
6 : *
7 : * LICENSE TERMS AND CONDITIONS
8 : *
9 : * The following License Terms and Conditions apply, unless a different
10 : * license is obtained from Japan Network Information Center ("JPNIC"),
11 : * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
12 : * Chiyoda-ku, Tokyo 101-0047, Japan.
13 : *
14 : * 1. Use, Modification and Redistribution (including distribution of any
15 : * modified or derived work) in source and/or binary forms is permitted
16 : * under this License Terms and Conditions.
17 : *
18 : * 2. Redistribution of source code must retain the copyright notices as they
19 : * appear in each source code file, this License Terms and Conditions.
20 : *
21 : * 3. Redistribution in binary form must reproduce the Copyright Notice,
22 : * this License Terms and Conditions, in the documentation and/or other
23 : * materials provided with the distribution. For the purposes of binary
24 : * distribution the "Copyright Notice" refers to the following language:
25 : * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
26 : *
27 : * 4. The name of JPNIC may not be used to endorse or promote products
28 : * derived from this Software without specific prior written approval of
29 : * JPNIC.
30 : *
31 : * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
32 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
34 : * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
35 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
36 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
38 : * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
42 : */
43 :
44 :
45 : #include <stddef.h>
46 : #include <stdlib.h>
47 : #include <string.h>
48 :
49 : #include "nsIDNKitInterface.h"
50 :
51 :
52 : #define RACE_2OCTET_MODE 0xd8
53 : #define RACE_ESCAPE 0xff
54 : #define RACE_ESCAPE_2ND 0x99
55 :
56 : /*
57 : * Compression type.
58 : */
59 : enum {
60 : compress_one, /* all characters are in a single row */
61 : compress_two, /* row 0 and another row */
62 : compress_none /* nope */
63 : };
64 :
65 :
66 : idn_result_t
67 0 : race_decode_decompress(const char *from, PRUint16 *buf, size_t buflen)
68 : {
69 0 : PRUint16 *p = buf;
70 0 : unsigned int bitbuf = 0;
71 0 : int bitlen = 0;
72 : unsigned int i, j;
73 : size_t len;
74 :
75 0 : while (*from != '\0') {
76 0 : int c = *from++;
77 : int x;
78 :
79 0 : if ('a' <= c && c <= 'z')
80 0 : x = c - 'a';
81 0 : else if ('A' <= c && c <= 'Z')
82 0 : x = c - 'A';
83 0 : else if ('2' <= c && c <= '7')
84 0 : x = c - '2' + 26;
85 : else
86 0 : return (idn_invalid_encoding);
87 :
88 0 : bitbuf = (bitbuf << 5) + x;
89 0 : bitlen += 5;
90 0 : if (bitlen >= 8) {
91 0 : *p++ = (bitbuf >> (bitlen - 8)) & 0xff;
92 0 : bitlen -= 8;
93 : }
94 : }
95 0 : len = p - buf;
96 :
97 : /*
98 : * Now 'buf' holds the decoded string.
99 : */
100 :
101 : /*
102 : * Decompress.
103 : */
104 0 : if (buf[0] == RACE_2OCTET_MODE) {
105 0 : if ((len - 1) % 2 != 0)
106 0 : return (idn_invalid_encoding);
107 0 : for (i = 1, j = 0; i < len; i += 2, j++)
108 0 : buf[j] = (buf[i] << 8) + buf[i + 1];
109 0 : len = j;
110 : } else {
111 0 : PRUint16 c = buf[0] << 8; /* higher octet */
112 :
113 0 : for (i = 1, j = 0; i < len; j++) {
114 0 : if (buf[i] == RACE_ESCAPE) {
115 0 : if (i + 1 >= len)
116 0 : return (idn_invalid_encoding);
117 0 : else if (buf[i + 1] == RACE_ESCAPE_2ND)
118 0 : buf[j] = c | 0xff;
119 : else
120 0 : buf[j] = buf[i + 1];
121 0 : i += 2;
122 :
123 0 : } else if (buf[i] == 0x99 && c == 0x00) {
124 : /*
125 : * The RACE specification says this is error.
126 : */
127 0 : return (idn_invalid_encoding);
128 :
129 : } else {
130 0 : buf[j] = c | buf[i++];
131 : }
132 : }
133 0 : len = j;
134 : }
135 0 : buf[len] = '\0';
136 :
137 0 : return (idn_success);
138 : }
139 :
140 : idn_result_t
141 0 : race_compress_encode(const PRUint16 *p, int compress_mode,
142 : char *to, size_t tolen)
143 : {
144 0 : PRUint32 bitbuf = *p++; /* bit stream buffer */
145 0 : int bitlen = 8; /* # of bits in 'bitbuf' */
146 :
147 0 : while (*p != '\0' || bitlen > 0) {
148 0 : unsigned int c = *p;
149 :
150 0 : if (c == '\0') {
151 : /* End of data. Flush. */
152 0 : bitbuf <<= (5 - bitlen);
153 0 : bitlen = 5;
154 0 : } else if (compress_mode == compress_none) {
155 : /* Push 16 bit data. */
156 0 : bitbuf = (bitbuf << 16) | c;
157 0 : bitlen += 16;
158 0 : p++;
159 : } else {/* compress_mode == compress_one/compress_two */
160 : /* Push 8 or 16 bit data. */
161 0 : if (compress_mode == compress_two &&
162 0 : (c & 0xff00) == 0) {
163 : /* Upper octet is zero (and not U1). */
164 0 : bitbuf = (bitbuf << 16) | 0xff00 | c;
165 0 : bitlen += 16;
166 0 : } else if ((c & 0xff) == 0xff) {
167 : /* Lower octet is 0xff. */
168 0 : bitbuf = (bitbuf << 16) |
169 : (RACE_ESCAPE << 8) | RACE_ESCAPE_2ND;
170 0 : bitlen += 16;
171 : } else {
172 : /* Just output lower octet. */
173 0 : bitbuf = (bitbuf << 8) | (c & 0xff);
174 0 : bitlen += 8;
175 : }
176 0 : p++;
177 : }
178 :
179 : /*
180 : * Output bits in 'bitbuf' in 5-bit unit.
181 : */
182 0 : while (bitlen >= 5) {
183 : int x;
184 :
185 : /* Get top 5 bits. */
186 0 : x = (bitbuf >> (bitlen - 5)) & 0x1f;
187 0 : bitlen -= 5;
188 :
189 : /* Encode. */
190 0 : if (x < 26)
191 0 : x += 'a';
192 : else
193 0 : x = (x - 26) + '2';
194 :
195 0 : if (tolen < 1)
196 0 : return (idn_buffer_overflow);
197 :
198 0 : *to++ = x;
199 0 : tolen--;
200 : }
201 : }
202 :
203 0 : if (tolen <= 0)
204 0 : return (idn_buffer_overflow);
205 :
206 0 : *to = '\0';
207 0 : return (idn_success);
208 : }
209 :
210 : int
211 0 : get_compress_mode(PRUint16 *p) {
212 0 : int zero = 0;
213 0 : unsigned int upper = 0;
214 0 : PRUint16 *modepos = p - 1;
215 :
216 0 : while (*p != '\0') {
217 0 : unsigned int hi = *p++ & 0xff00;
218 :
219 0 : if (hi == 0) {
220 0 : zero++;
221 0 : } else if (hi == upper) {
222 : ;
223 0 : } else if (upper == 0) {
224 0 : upper = hi;
225 : } else {
226 0 : *modepos = RACE_2OCTET_MODE;
227 0 : return (compress_none);
228 : }
229 : }
230 0 : *modepos = upper >> 8;
231 0 : if (upper > 0 && zero > 0)
232 0 : return (compress_two);
233 : else
234 0 : return (compress_one);
235 : }
|