netwerk/dns/nameprep.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/dns/nameprep.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,347 @@
     1.4 +/*
     1.5 + * Copyright (c) 2001,2002 Japan Network Information Center.
     1.6 + * All rights reserved.
     1.7 + *  
     1.8 + * By using this file, you agree to the terms and conditions set forth bellow.
     1.9 + * 
    1.10 + * 			LICENSE TERMS AND CONDITIONS 
    1.11 + * 
    1.12 + * The following License Terms and Conditions apply, unless a different
    1.13 + * license is obtained from Japan Network Information Center ("JPNIC"),
    1.14 + * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
    1.15 + * Chiyoda-ku, Tokyo 101-0047, Japan.
    1.16 + * 
    1.17 + * 1. Use, Modification and Redistribution (including distribution of any
    1.18 + *    modified or derived work) in source and/or binary forms is permitted
    1.19 + *    under this License Terms and Conditions.
    1.20 + * 
    1.21 + * 2. Redistribution of source code must retain the copyright notices as they
    1.22 + *    appear in each source code file, this License Terms and Conditions.
    1.23 + * 
    1.24 + * 3. Redistribution in binary form must reproduce the Copyright Notice,
    1.25 + *    this License Terms and Conditions, in the documentation and/or other
    1.26 + *    materials provided with the distribution.  For the purposes of binary
    1.27 + *    distribution the "Copyright Notice" refers to the following language:
    1.28 + *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
    1.29 + * 
    1.30 + * 4. The name of JPNIC may not be used to endorse or promote products
    1.31 + *    derived from this Software without specific prior written approval of
    1.32 + *    JPNIC.
    1.33 + * 
    1.34 + * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
    1.35 + *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    1.36 + *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    1.37 + *    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JPNIC BE LIABLE
    1.38 + *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.39 + *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.40 + *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
    1.41 + *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    1.42 + *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    1.43 + *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    1.44 + *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
    1.45 + */
    1.46 +
    1.47 +
    1.48 +#include <stdlib.h>
    1.49 +#include <string.h>
    1.50 +
    1.51 +#include "nsIDNKitInterface.h"
    1.52 +
    1.53 +#define UCS_MAX		0x7fffffff
    1.54 +#define UNICODE_MAX	0x10ffff
    1.55 +
    1.56 +
    1.57 +/*
    1.58 + * Load NAMEPREP compiled tables.
    1.59 + */
    1.60 +#include "nameprepdata.c"
    1.61 +
    1.62 +/*
    1.63 + * Define mapping/checking functions for each version of the draft.
    1.64 + */
    1.65 +
    1.66 +#define VERSION id11
    1.67 +#include "nameprep_template.c"
    1.68 +#undef VERSION
    1.69 +
    1.70 +typedef const char	*(*nameprep_mapproc)(uint32_t v);
    1.71 +typedef int		(*nameprep_checkproc)(uint32_t v);
    1.72 +typedef idn_biditype_t	(*nameprep_biditypeproc)(uint32_t v);
    1.73 +
    1.74 +static struct idn_nameprep {
    1.75 +	char *version;
    1.76 +	nameprep_mapproc map_proc;
    1.77 +	nameprep_checkproc prohibited_proc;
    1.78 +	nameprep_checkproc unassigned_proc;
    1.79 +	nameprep_biditypeproc biditype_proc;
    1.80 +} nameprep_versions[] = {
    1.81 +#define MAKE_NAMEPREP_HANDLE(version, id) \
    1.82 +	{ version, \
    1.83 +	  compose_sym2(nameprep_map_, id), \
    1.84 +	  compose_sym2(nameprep_prohibited_, id), \
    1.85 +	  compose_sym2(nameprep_unassigned_, id), \
    1.86 +	  compose_sym2(nameprep_biditype_, id), }
    1.87 +	MAKE_NAMEPREP_HANDLE("nameprep-11", id11),
    1.88 +	{ NULL, NULL, NULL, NULL, NULL },
    1.89 +};
    1.90 +
    1.91 +static idn_result_t	idn_nameprep_check(nameprep_checkproc proc,
    1.92 +					   const uint32_t *str,
    1.93 +					   const uint32_t **found);
    1.94 +
    1.95 +idn_result_t
    1.96 +idn_nameprep_create(const char *version, idn_nameprep_t *handlep) {
    1.97 +	idn_nameprep_t handle;
    1.98 +
    1.99 +	assert(handlep != NULL);
   1.100 +
   1.101 +	TRACE(("idn_nameprep_create(version=%-.50s)\n",
   1.102 +	       version == NULL ? "<NULL>" : version));
   1.103 +
   1.104 +	if (version == NULL)
   1.105 +		version = IDN_NAMEPREP_CURRENT;
   1.106 +
   1.107 +	/*
   1.108 +	 * Lookup table for the specified version.  Since the number of
   1.109 +	 * versions won't be large (I don't want see draft-23 or such :-),
   1.110 +	 * simple linear search is OK.
   1.111 +	 */
   1.112 +	for (handle = nameprep_versions; handle->version != NULL; handle++) {
   1.113 +		if (strcmp(handle->version, version) == 0) {
   1.114 +			*handlep = handle;
   1.115 +			return (idn_success);
   1.116 +		}
   1.117 +	}
   1.118 +	return (idn_notfound);
   1.119 +}
   1.120 +
   1.121 +void
   1.122 +idn_nameprep_destroy(idn_nameprep_t handle) {
   1.123 +	assert(handle != NULL);
   1.124 +
   1.125 +	TRACE(("idn_nameprep_destroy()\n"));
   1.126 +
   1.127 +	/* Nothing to do. */
   1.128 +}
   1.129 +
   1.130 +idn_result_t
   1.131 +idn_nameprep_map(idn_nameprep_t handle, const uint32_t *from,
   1.132 +		 uint32_t *to, size_t tolen) {
   1.133 +	assert(handle != NULL && from != NULL && to != NULL);
   1.134 +
   1.135 +	TRACE(("idn_nameprep_map(ctx=%s, from=\"%s\")\n",
   1.136 +	       handle->version, idn__debug_ucs4xstring(from, 50)));
   1.137 +
   1.138 +	while (*from != '\0') {
   1.139 +		uint32_t v = *from;
   1.140 +		const char *mapped;
   1.141 +
   1.142 +		if (v > UCS_MAX) {
   1.143 +			/* This cannot happen, but just in case.. */
   1.144 +			return (idn_invalid_codepoint);
   1.145 +		} else if (v > UNICODE_MAX) {
   1.146 +			/* No mapping is possible. */
   1.147 +			mapped = NULL;
   1.148 +		} else {
   1.149 +			/* Try mapping. */
   1.150 +			mapped = (*handle->map_proc)(v);
   1.151 +		}
   1.152 +
   1.153 +		if (mapped == NULL) {
   1.154 +			/* No mapping. Just copy verbatim. */
   1.155 +			if (tolen < 1)
   1.156 +				return (idn_buffer_overflow);
   1.157 +			*to++ = v;
   1.158 +			tolen--;
   1.159 +		} else {
   1.160 +			const unsigned char *mappeddata;
   1.161 +			size_t mappedlen;
   1.162 +
   1.163 +			mappeddata = (const unsigned char *)mapped + 1;
   1.164 +			mappedlen = *mapped;
   1.165 +
   1.166 +			if (tolen < (mappedlen + 3) / 4)
   1.167 +				return (idn_buffer_overflow);
   1.168 +			tolen -= (mappedlen + 3) / 4;
   1.169 +			while (mappedlen >= 4) {
   1.170 +				*to  = *mappeddata++;
   1.171 +				*to |= *mappeddata++ <<  8;
   1.172 +				*to |= *mappeddata++ << 16;
   1.173 +				*to |= *mappeddata++ << 24;
   1.174 +				mappedlen -= 4;
   1.175 +				to++;
   1.176 +			}
   1.177 +			if (mappedlen > 0) {
   1.178 +				*to  = *mappeddata++;
   1.179 +				*to |= (mappedlen >= 2) ?
   1.180 +				       *mappeddata++ <<  8: 0;
   1.181 +				*to |= (mappedlen >= 3) ?
   1.182 +				       *mappeddata++ << 16: 0;
   1.183 +				to++;
   1.184 +			}
   1.185 +		}
   1.186 +		from++;
   1.187 +	}
   1.188 +	if (tolen == 0)
   1.189 +		return (idn_buffer_overflow);
   1.190 +	*to = '\0';
   1.191 +	return (idn_success);
   1.192 +}
   1.193 +
   1.194 +idn_result_t
   1.195 +idn_nameprep_isprohibited(idn_nameprep_t handle, const uint32_t *str,
   1.196 +			  const uint32_t **found) {
   1.197 +	assert(handle != NULL && str != NULL && found != NULL);
   1.198 +
   1.199 +	TRACE(("idn_nameprep_isprohibited(ctx=%s, str=\"%s\")\n",
   1.200 +	       handle->version, idn__debug_ucs4xstring(str, 50)));
   1.201 +
   1.202 +	return (idn_nameprep_check(handle->prohibited_proc, str, found));
   1.203 +}
   1.204 +		
   1.205 +idn_result_t
   1.206 +idn_nameprep_isunassigned(idn_nameprep_t handle, const uint32_t *str,
   1.207 +			  const uint32_t **found) {
   1.208 +	assert(handle != NULL && str != NULL && found != NULL);
   1.209 +
   1.210 +	TRACE(("idn_nameprep_isunassigned(handle->version, str=\"%s\")\n",
   1.211 +	       handle->version, idn__debug_ucs4xstring(str, 50)));
   1.212 +
   1.213 +	return (idn_nameprep_check(handle->unassigned_proc, str, found));
   1.214 +}
   1.215 +		
   1.216 +static idn_result_t
   1.217 +idn_nameprep_check(nameprep_checkproc proc, const uint32_t *str,
   1.218 +		   const uint32_t **found) {
   1.219 +	uint32_t v;
   1.220 +
   1.221 +	while (*str != '\0') {
   1.222 +		v = *str;
   1.223 +
   1.224 +		if (v > UCS_MAX) {
   1.225 +			/* This cannot happen, but just in case.. */
   1.226 +			return (idn_invalid_codepoint);
   1.227 +		} else if (v > UNICODE_MAX) {
   1.228 +			/* It is invalid.. */
   1.229 +			*found = str;
   1.230 +			return (idn_success);
   1.231 +		} else if ((*proc)(v)) {
   1.232 +			*found = str;
   1.233 +			return (idn_success);
   1.234 +		}
   1.235 +		str++;
   1.236 +	}
   1.237 +	*found = NULL;
   1.238 +	return (idn_success);
   1.239 +}
   1.240 +
   1.241 +idn_result_t
   1.242 +idn_nameprep_isvalidbidi(idn_nameprep_t handle, const uint32_t *str,
   1.243 +			 const uint32_t **found) {
   1.244 +	uint32_t v;
   1.245 +	idn_biditype_t first_char;
   1.246 +	idn_biditype_t last_char;
   1.247 +	int found_r_al;
   1.248 +
   1.249 +	assert(handle != NULL && str != NULL && found != NULL);
   1.250 +
   1.251 +	TRACE(("idn_nameprep_isvalidbidi(ctx=%s, str=\"%s\")\n",
   1.252 +	       handle->version, idn__debug_ucs4xstring(str, 50)));
   1.253 +
   1.254 +	if (*str == '\0') {
   1.255 +		*found = NULL;
   1.256 +		return (idn_success);
   1.257 +	}
   1.258 +
   1.259 +	/*
   1.260 +	 * check first character's type and initialize variables.
   1.261 +	 */
   1.262 +	found_r_al = 0;
   1.263 +	if (*str > UCS_MAX) {
   1.264 +		/* This cannot happen, but just in case.. */
   1.265 +		return (idn_invalid_codepoint);
   1.266 +	} else if (*str > UNICODE_MAX) {
   1.267 +		/* It is invalid.. */
   1.268 +		*found = str;
   1.269 +		return (idn_success);
   1.270 +	}
   1.271 +	first_char = last_char = (*(handle->biditype_proc))(*str);
   1.272 +	if (first_char == idn_biditype_r_al) {
   1.273 +		found_r_al = 1;
   1.274 +	}
   1.275 +	str++;
   1.276 +
   1.277 +	/*
   1.278 +	 * see whether string is valid or not.
   1.279 +	 */
   1.280 +	while (*str != '\0') {
   1.281 +		v = *str;
   1.282 +
   1.283 +		if (v > UCS_MAX) {
   1.284 +			/* This cannot happen, but just in case.. */
   1.285 +			return (idn_invalid_codepoint);
   1.286 +		} else if (v > UNICODE_MAX) {
   1.287 +			/* It is invalid.. */
   1.288 +			*found = str;
   1.289 +			return (idn_success);
   1.290 +		} else { 
   1.291 +			last_char = (*(handle->biditype_proc))(v);
   1.292 +			if (found_r_al && last_char == idn_biditype_l) {
   1.293 +				*found = str;
   1.294 +				return (idn_success);
   1.295 +			}
   1.296 +			if (first_char != idn_biditype_r_al && last_char == idn_biditype_r_al) {
   1.297 +				*found = str;
   1.298 +				return (idn_success);
   1.299 +			}
   1.300 +			if (last_char == idn_biditype_r_al) {
   1.301 +				found_r_al = 1;
   1.302 +			}
   1.303 +		}
   1.304 +		str++;
   1.305 +	}
   1.306 +
   1.307 +	if (found_r_al) {
   1.308 +		if (last_char != idn_biditype_r_al) {
   1.309 +			*found = str - 1;
   1.310 +			return (idn_success);
   1.311 +		}
   1.312 +	}
   1.313 +
   1.314 +	*found = NULL;
   1.315 +	return (idn_success);
   1.316 +}
   1.317 +
   1.318 +idn_result_t
   1.319 +idn_nameprep_createproc(const char *parameter, void **handlep) {
   1.320 +	return idn_nameprep_create(parameter, (idn_nameprep_t *)handlep);
   1.321 +}
   1.322 +
   1.323 +void
   1.324 +idn_nameprep_destroyproc(void *handle) {
   1.325 +	idn_nameprep_destroy((idn_nameprep_t)handle);
   1.326 +}
   1.327 +
   1.328 +idn_result_t
   1.329 +idn_nameprep_mapproc(void *handle, const uint32_t *from,
   1.330 +		      uint32_t *to, size_t tolen) {
   1.331 +	return idn_nameprep_map((idn_nameprep_t)handle, from, to, tolen);
   1.332 +}
   1.333 +
   1.334 +idn_result_t
   1.335 +idn_nameprep_prohibitproc(void *handle, const uint32_t *str,
   1.336 +			   const uint32_t **found) {
   1.337 +	return idn_nameprep_isprohibited((idn_nameprep_t)handle, str, found);
   1.338 +}
   1.339 +
   1.340 +idn_result_t
   1.341 +idn_nameprep_unassignedproc(void *handle, const uint32_t *str,
   1.342 +			     const uint32_t **found) {
   1.343 +	return idn_nameprep_isunassigned((idn_nameprep_t)handle, str, found);
   1.344 +}
   1.345 +
   1.346 +idn_result_t
   1.347 +idn_nameprep_bidiproc(void *handle, const uint32_t *str,
   1.348 +		      const uint32_t **found) {
   1.349 +	return idn_nameprep_isvalidbidi((idn_nameprep_t)handle, str, found);
   1.350 +}

mercurial