1226031Sstas/* 2226031Sstas * Copyright (c) 2004 Kungliga Tekniska H��gskolan 3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4226031Sstas * All rights reserved. 5226031Sstas * 6226031Sstas * Redistribution and use in source and binary forms, with or without 7226031Sstas * modification, are permitted provided that the following conditions 8226031Sstas * are met: 9226031Sstas * 10226031Sstas * 1. Redistributions of source code must retain the above copyright 11226031Sstas * notice, this list of conditions and the following disclaimer. 12226031Sstas * 13226031Sstas * 2. Redistributions in binary form must reproduce the above copyright 14226031Sstas * notice, this list of conditions and the following disclaimer in the 15226031Sstas * documentation and/or other materials provided with the distribution. 16226031Sstas * 17226031Sstas * 3. Neither the name of the Institute nor the names of its contributors 18226031Sstas * may be used to endorse or promote products derived from this software 19226031Sstas * without specific prior written permission. 20226031Sstas * 21226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24226031Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31226031Sstas * SUCH DAMAGE. 32226031Sstas */ 33226031Sstas 34226031Sstas#ifdef HAVE_CONFIG_H 35226031Sstas#include <config.h> 36226031Sstas#endif 37226031Sstas#include <string.h> 38226031Sstas#include "windlocl.h" 39226031Sstas 40226031Sstasstatic const unsigned base = 36; 41226031Sstasstatic const unsigned t_min = 1; 42226031Sstasstatic const unsigned t_max = 26; 43226031Sstasstatic const unsigned skew = 38; 44226031Sstasstatic const unsigned damp = 700; 45226031Sstasstatic const unsigned initial_n = 128; 46226031Sstasstatic const unsigned initial_bias = 72; 47226031Sstas 48226031Sstasstatic unsigned 49226031Sstasdigit(unsigned n) 50226031Sstas{ 51226031Sstas return "abcdefghijklmnopqrstuvwxyz0123456789"[n]; 52226031Sstas} 53226031Sstas 54226031Sstasstatic unsigned 55226031Sstasadapt(unsigned delta, unsigned numpoints, int first) 56226031Sstas{ 57226031Sstas unsigned k; 58226031Sstas 59226031Sstas if (first) 60226031Sstas delta = delta / damp; 61226031Sstas else 62226031Sstas delta /= 2; 63226031Sstas delta += delta / numpoints; 64226031Sstas k = 0; 65226031Sstas while (delta > ((base - t_min) * t_max) / 2) { 66226031Sstas delta /= base - t_min; 67226031Sstas k += base; 68226031Sstas } 69226031Sstas return k + (((base - t_min + 1) * delta) / (delta + skew)); 70226031Sstas} 71226031Sstas 72226031Sstas/** 73226031Sstas * Convert an UCS4 string to a puny-coded DNS label string suitable 74226031Sstas * when combined with delimiters and other labels for DNS lookup. 75226031Sstas * 76226031Sstas * @param in an UCS4 string to convert 77226031Sstas * @param in_len the length of in. 78226031Sstas * @param out the resulting puny-coded string. The string is not NUL 79226031Sstas * terminatied. 80226031Sstas * @param out_len before processing out_len should be the length of 81226031Sstas * the out variable, after processing it will be the length of the out 82226031Sstas * string. 83226031Sstas * 84226031Sstas * @return returns 0 on success, an wind error code otherwise 85226031Sstas * @ingroup wind 86226031Sstas */ 87226031Sstas 88226031Sstasint 89226031Sstaswind_punycode_label_toascii(const uint32_t *in, size_t in_len, 90226031Sstas char *out, size_t *out_len) 91226031Sstas{ 92226031Sstas unsigned n = initial_n; 93226031Sstas unsigned delta = 0; 94226031Sstas unsigned bias = initial_bias; 95226031Sstas unsigned h = 0; 96226031Sstas unsigned b; 97226031Sstas unsigned i; 98226031Sstas unsigned o = 0; 99226031Sstas unsigned m; 100226031Sstas 101226031Sstas for (i = 0; i < in_len; ++i) { 102226031Sstas if (in[i] < 0x80) { 103226031Sstas ++h; 104226031Sstas if (o >= *out_len) 105226031Sstas return WIND_ERR_OVERRUN; 106226031Sstas out[o++] = in[i]; 107226031Sstas } 108226031Sstas } 109226031Sstas b = h; 110226031Sstas if (b > 0) { 111226031Sstas if (o >= *out_len) 112226031Sstas return WIND_ERR_OVERRUN; 113226031Sstas out[o++] = 0x2D; 114226031Sstas } 115226031Sstas /* is this string punycoded */ 116226031Sstas if (h < in_len) { 117226031Sstas if (o + 4 >= *out_len) 118226031Sstas return WIND_ERR_OVERRUN; 119226031Sstas memmove(out + 4, out, o); 120226031Sstas memcpy(out, "xn--", 4); 121226031Sstas o += 4; 122226031Sstas } 123226031Sstas 124226031Sstas while (h < in_len) { 125226031Sstas m = (unsigned)-1; 126226031Sstas for (i = 0; i < in_len; ++i) 127226031Sstas if(in[i] < m && in[i] >= n) 128226031Sstas m = in[i]; 129226031Sstas 130226031Sstas delta += (m - n) * (h + 1); 131226031Sstas n = m; 132226031Sstas for (i = 0; i < in_len; ++i) { 133226031Sstas if (in[i] < n) { 134226031Sstas ++delta; 135226031Sstas } else if (in[i] == n) { 136226031Sstas unsigned q = delta; 137226031Sstas unsigned k; 138226031Sstas for (k = base; ; k += base) { 139226031Sstas unsigned t; 140226031Sstas if (k <= bias) 141226031Sstas t = t_min; 142226031Sstas else if (k >= bias + t_max) 143226031Sstas t = t_max; 144226031Sstas else 145226031Sstas t = k - bias; 146226031Sstas if (q < t) 147226031Sstas break; 148226031Sstas if (o >= *out_len) 149226031Sstas return WIND_ERR_OVERRUN; 150226031Sstas out[o++] = digit(t + ((q - t) % (base - t))); 151226031Sstas q = (q - t) / (base - t); 152226031Sstas } 153226031Sstas if (o >= *out_len) 154226031Sstas return WIND_ERR_OVERRUN; 155226031Sstas out[o++] = digit(q); 156226031Sstas /* output */ 157226031Sstas bias = adapt(delta, h + 1, h == b); 158226031Sstas delta = 0; 159226031Sstas ++h; 160226031Sstas } 161226031Sstas } 162226031Sstas ++delta; 163226031Sstas ++n; 164226031Sstas } 165226031Sstas 166226031Sstas *out_len = o; 167226031Sstas return 0; 168226031Sstas} 169