netwerk/dns/race.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial