2 7957cbd9 2021-01-27 op * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
4 7957cbd9 2021-01-27 op * Permission to use, copy, modify, and distribute this software for any
5 7957cbd9 2021-01-27 op * purpose with or without fee is hereby granted, provided that the above
6 7957cbd9 2021-01-27 op * copyright notice and this permission notice appear in all copies.
8 7957cbd9 2021-01-27 op * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 7957cbd9 2021-01-27 op * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 7957cbd9 2021-01-27 op * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 7957cbd9 2021-01-27 op * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 7957cbd9 2021-01-27 op * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 7957cbd9 2021-01-27 op * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 7957cbd9 2021-01-27 op * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 7957cbd9 2021-01-27 op #include <stddef.h>
18 7957cbd9 2021-01-27 op #include <stdint.h>
19 7957cbd9 2021-01-27 op #include <string.h>
21 7957cbd9 2021-01-27 op #include "gmid.h"
23 7957cbd9 2021-01-27 op #define BASE 36
24 7957cbd9 2021-01-27 op #define TMIN 1
25 7957cbd9 2021-01-27 op #define TMAX 26
26 7957cbd9 2021-01-27 op #define SKEW 38
27 7957cbd9 2021-01-27 op #define DAMP 700
28 7957cbd9 2021-01-27 op #define IBIAS 72
29 7957cbd9 2021-01-27 op #define IN 128
32 7957cbd9 2021-01-27 op adapt(int delta, int numpoints, int firsttime)
36 7957cbd9 2021-01-27 op if (firsttime)
37 7957cbd9 2021-01-27 op delta = delta / DAMP;
39 7957cbd9 2021-01-27 op delta = delta / 2;
41 7957cbd9 2021-01-27 op delta += (delta / numpoints);
44 7957cbd9 2021-01-27 op while (delta > ((BASE - TMIN) * TMAX) / 2) {
45 7957cbd9 2021-01-27 op delta = delta / (BASE - TMIN);
48 7957cbd9 2021-01-27 op return k + (((BASE - TMIN + 1) * delta) / (delta + SKEW));
51 7957cbd9 2021-01-27 op static const char *
52 7957cbd9 2021-01-27 op copy_until_delimiter(const char *s, char *out, size_t len)
54 7957cbd9 2021-01-27 op char *end, *t;
56 7957cbd9 2021-01-27 op end = strchr(s, '\0');
57 7957cbd9 2021-01-27 op if (end - s > len)
60 7957cbd9 2021-01-27 op for (t = end; t >= s; --t)
61 7957cbd9 2021-01-27 op if (*t == '-')
67 7957cbd9 2021-01-27 op for (; s < t; ++s, ++out) {
76 7957cbd9 2021-01-27 op static unsigned int
77 7957cbd9 2021-01-27 op digit_value(char c)
79 7957cbd9 2021-01-27 op if ('A' <= c && c <= 'Z')
80 7957cbd9 2021-01-27 op return c - 'A';
82 7957cbd9 2021-01-27 op if ('a' <= c && c <= 'z')
83 7957cbd9 2021-01-27 op return c - 'a';
85 7957cbd9 2021-01-27 op if ('0' <= c && c <= '9')
86 7957cbd9 2021-01-27 op return 26 + c - '0';
92 7957cbd9 2021-01-27 op insert(char *out, size_t len, int codepoint, size_t i)
95 7957cbd9 2021-01-27 op size_t outlen;
98 7957cbd9 2021-01-27 op if (codepoint <= 0x7F)
100 7957cbd9 2021-01-27 op else if (codepoint <= 0x7FF)
102 7957cbd9 2021-01-27 op else if (codepoint <= 0xFFFF)
104 7957cbd9 2021-01-27 op else if (codepoint <= 0x10FFFF)
109 7957cbd9 2021-01-27 op if ((t = utf8_nth(out, i)) == NULL)
111 7957cbd9 2021-01-27 op if (t + l >= out + len)
114 7957cbd9 2021-01-27 op memmove(t + l, t, strlen(t));
118 7957cbd9 2021-01-27 op t[1] = ( codepoint & 0x3F) + 0x80;
119 7957cbd9 2021-01-27 op t[0] = ((codepoint >> 6) & 0x1F) + 0xC0;
122 7957cbd9 2021-01-27 op t[2] = ( codepoint & 0x3F) + 0x80;
123 7957cbd9 2021-01-27 op t[1] = ((codepoint >> 6) & 0x3F) + 0x80;
124 7957cbd9 2021-01-27 op t[0] = ((codepoint >> 12) & 0x0F) + 0xE0;
127 7957cbd9 2021-01-27 op t[3] = ( codepoint & 0x3F) + 0x80;
128 7957cbd9 2021-01-27 op t[2] = ((codepoint >> 6) & 0x3F) + 0x80;
129 7957cbd9 2021-01-27 op t[1] = ((codepoint >> 12) & 0x3F) + 0x80;
130 7957cbd9 2021-01-27 op t[0] = ((codepoint >> 18) & 0x07) + 0xF0;
137 7957cbd9 2021-01-27 op decode(const char *str, char *out, size_t len)
141 7957cbd9 2021-01-27 op unsigned int oldi, bias, w, k, digit, t;
142 7957cbd9 2021-01-27 op unsigned int numpoints;
143 7957cbd9 2021-01-27 op const char *s;
145 7957cbd9 2021-01-27 op if (str == NULL || len <= 4)
148 7957cbd9 2021-01-27 op /* todo: starts_with */
149 7957cbd9 2021-01-27 op if (strstr(str, "xn--") != str) {
150 7957cbd9 2021-01-27 op strncpy(out, str, len);
154 7957cbd9 2021-01-27 op /* skip the xn-- */
157 7957cbd9 2021-01-27 op if (strchr(str, '-') != NULL) {
158 7957cbd9 2021-01-27 op if ((s = copy_until_delimiter(str, out, len)) == NULL)
160 7957cbd9 2021-01-27 op if (*s == '-')
165 7957cbd9 2021-01-27 op numpoints = strlen(out);
169 7957cbd9 2021-01-27 op bias = IBIAS;
171 7957cbd9 2021-01-27 op while (*s != '\0') {
175 7957cbd9 2021-01-27 op for (k = BASE; ; k += BASE) {
176 7957cbd9 2021-01-27 op if (*s == '\0')
178 7957cbd9 2021-01-27 op /* fail eventually? */
179 7957cbd9 2021-01-27 op digit = digit_value(*s);
182 7957cbd9 2021-01-27 op /* fail on overflow */
183 7957cbd9 2021-01-27 op i += digit * w;
185 7957cbd9 2021-01-27 op if (k <= bias)
187 7957cbd9 2021-01-27 op else if (k >= bias + TMAX)
190 7957cbd9 2021-01-27 op t = k - bias;
192 7957cbd9 2021-01-27 op if (digit < t)
194 7957cbd9 2021-01-27 op w *= (BASE - t);
197 7957cbd9 2021-01-27 op bias = adapt(i - oldi, numpoints+1, oldi == 0);
198 7957cbd9 2021-01-27 op n += i / (numpoints+1); /* fail on overflow */
199 7957cbd9 2021-01-27 op i = i % (numpoints+1);
201 7957cbd9 2021-01-27 op if (!insert(out, len, n, i))
211 7957cbd9 2021-01-27 op end_of_component(const char *hostname)
213 7957cbd9 2021-01-27 op for (; *hostname != '\0' && *hostname != '.'; ++hostname)
215 7957cbd9 2021-01-27 op return hostname;
219 7957cbd9 2021-01-27 op puny_decode(const char *hostname, char *out, size_t len)
221 7957cbd9 2021-01-27 op char comp[DOMAIN_NAME_LEN];
222 7957cbd9 2021-01-27 op const char *s, *end;
225 7957cbd9 2021-01-27 op memset(out, 0, len);
227 7957cbd9 2021-01-27 op s = hostname;
229 7957cbd9 2021-01-27 op end = end_of_component(s);
230 7957cbd9 2021-01-27 op if (end - s >= sizeof(comp))
233 7957cbd9 2021-01-27 op memcpy(comp, s, end - s);
234 7957cbd9 2021-01-27 op comp[end - s] = '\0';
236 7957cbd9 2021-01-27 op if (!decode(comp, out, len))
239 7957cbd9 2021-01-27 op if (*end == '\0')
242 7957cbd9 2021-01-27 op if (strlcat(out, ".", len) >= len)
245 7957cbd9 2021-01-27 op l = strlen(out);
246 7957cbd9 2021-01-27 op if (l >= len)