netwerk/dns/nameprep.c

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 /*
     2  * Copyright (c) 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  */
    45 #include <stdlib.h>
    46 #include <string.h>
    48 #include "nsIDNKitInterface.h"
    50 #define UCS_MAX		0x7fffffff
    51 #define UNICODE_MAX	0x10ffff
    54 /*
    55  * Load NAMEPREP compiled tables.
    56  */
    57 #include "nameprepdata.c"
    59 /*
    60  * Define mapping/checking functions for each version of the draft.
    61  */
    63 #define VERSION id11
    64 #include "nameprep_template.c"
    65 #undef VERSION
    67 typedef const char	*(*nameprep_mapproc)(uint32_t v);
    68 typedef int		(*nameprep_checkproc)(uint32_t v);
    69 typedef idn_biditype_t	(*nameprep_biditypeproc)(uint32_t v);
    71 static struct idn_nameprep {
    72 	char *version;
    73 	nameprep_mapproc map_proc;
    74 	nameprep_checkproc prohibited_proc;
    75 	nameprep_checkproc unassigned_proc;
    76 	nameprep_biditypeproc biditype_proc;
    77 } nameprep_versions[] = {
    78 #define MAKE_NAMEPREP_HANDLE(version, id) \
    79 	{ version, \
    80 	  compose_sym2(nameprep_map_, id), \
    81 	  compose_sym2(nameprep_prohibited_, id), \
    82 	  compose_sym2(nameprep_unassigned_, id), \
    83 	  compose_sym2(nameprep_biditype_, id), }
    84 	MAKE_NAMEPREP_HANDLE("nameprep-11", id11),
    85 	{ NULL, NULL, NULL, NULL, NULL },
    86 };
    88 static idn_result_t	idn_nameprep_check(nameprep_checkproc proc,
    89 					   const uint32_t *str,
    90 					   const uint32_t **found);
    92 idn_result_t
    93 idn_nameprep_create(const char *version, idn_nameprep_t *handlep) {
    94 	idn_nameprep_t handle;
    96 	assert(handlep != NULL);
    98 	TRACE(("idn_nameprep_create(version=%-.50s)\n",
    99 	       version == NULL ? "<NULL>" : version));
   101 	if (version == NULL)
   102 		version = IDN_NAMEPREP_CURRENT;
   104 	/*
   105 	 * Lookup table for the specified version.  Since the number of
   106 	 * versions won't be large (I don't want see draft-23 or such :-),
   107 	 * simple linear search is OK.
   108 	 */
   109 	for (handle = nameprep_versions; handle->version != NULL; handle++) {
   110 		if (strcmp(handle->version, version) == 0) {
   111 			*handlep = handle;
   112 			return (idn_success);
   113 		}
   114 	}
   115 	return (idn_notfound);
   116 }
   118 void
   119 idn_nameprep_destroy(idn_nameprep_t handle) {
   120 	assert(handle != NULL);
   122 	TRACE(("idn_nameprep_destroy()\n"));
   124 	/* Nothing to do. */
   125 }
   127 idn_result_t
   128 idn_nameprep_map(idn_nameprep_t handle, const uint32_t *from,
   129 		 uint32_t *to, size_t tolen) {
   130 	assert(handle != NULL && from != NULL && to != NULL);
   132 	TRACE(("idn_nameprep_map(ctx=%s, from=\"%s\")\n",
   133 	       handle->version, idn__debug_ucs4xstring(from, 50)));
   135 	while (*from != '\0') {
   136 		uint32_t v = *from;
   137 		const char *mapped;
   139 		if (v > UCS_MAX) {
   140 			/* This cannot happen, but just in case.. */
   141 			return (idn_invalid_codepoint);
   142 		} else if (v > UNICODE_MAX) {
   143 			/* No mapping is possible. */
   144 			mapped = NULL;
   145 		} else {
   146 			/* Try mapping. */
   147 			mapped = (*handle->map_proc)(v);
   148 		}
   150 		if (mapped == NULL) {
   151 			/* No mapping. Just copy verbatim. */
   152 			if (tolen < 1)
   153 				return (idn_buffer_overflow);
   154 			*to++ = v;
   155 			tolen--;
   156 		} else {
   157 			const unsigned char *mappeddata;
   158 			size_t mappedlen;
   160 			mappeddata = (const unsigned char *)mapped + 1;
   161 			mappedlen = *mapped;
   163 			if (tolen < (mappedlen + 3) / 4)
   164 				return (idn_buffer_overflow);
   165 			tolen -= (mappedlen + 3) / 4;
   166 			while (mappedlen >= 4) {
   167 				*to  = *mappeddata++;
   168 				*to |= *mappeddata++ <<  8;
   169 				*to |= *mappeddata++ << 16;
   170 				*to |= *mappeddata++ << 24;
   171 				mappedlen -= 4;
   172 				to++;
   173 			}
   174 			if (mappedlen > 0) {
   175 				*to  = *mappeddata++;
   176 				*to |= (mappedlen >= 2) ?
   177 				       *mappeddata++ <<  8: 0;
   178 				*to |= (mappedlen >= 3) ?
   179 				       *mappeddata++ << 16: 0;
   180 				to++;
   181 			}
   182 		}
   183 		from++;
   184 	}
   185 	if (tolen == 0)
   186 		return (idn_buffer_overflow);
   187 	*to = '\0';
   188 	return (idn_success);
   189 }
   191 idn_result_t
   192 idn_nameprep_isprohibited(idn_nameprep_t handle, const uint32_t *str,
   193 			  const uint32_t **found) {
   194 	assert(handle != NULL && str != NULL && found != NULL);
   196 	TRACE(("idn_nameprep_isprohibited(ctx=%s, str=\"%s\")\n",
   197 	       handle->version, idn__debug_ucs4xstring(str, 50)));
   199 	return (idn_nameprep_check(handle->prohibited_proc, str, found));
   200 }
   202 idn_result_t
   203 idn_nameprep_isunassigned(idn_nameprep_t handle, const uint32_t *str,
   204 			  const uint32_t **found) {
   205 	assert(handle != NULL && str != NULL && found != NULL);
   207 	TRACE(("idn_nameprep_isunassigned(handle->version, str=\"%s\")\n",
   208 	       handle->version, idn__debug_ucs4xstring(str, 50)));
   210 	return (idn_nameprep_check(handle->unassigned_proc, str, found));
   211 }
   213 static idn_result_t
   214 idn_nameprep_check(nameprep_checkproc proc, const uint32_t *str,
   215 		   const uint32_t **found) {
   216 	uint32_t v;
   218 	while (*str != '\0') {
   219 		v = *str;
   221 		if (v > UCS_MAX) {
   222 			/* This cannot happen, but just in case.. */
   223 			return (idn_invalid_codepoint);
   224 		} else if (v > UNICODE_MAX) {
   225 			/* It is invalid.. */
   226 			*found = str;
   227 			return (idn_success);
   228 		} else if ((*proc)(v)) {
   229 			*found = str;
   230 			return (idn_success);
   231 		}
   232 		str++;
   233 	}
   234 	*found = NULL;
   235 	return (idn_success);
   236 }
   238 idn_result_t
   239 idn_nameprep_isvalidbidi(idn_nameprep_t handle, const uint32_t *str,
   240 			 const uint32_t **found) {
   241 	uint32_t v;
   242 	idn_biditype_t first_char;
   243 	idn_biditype_t last_char;
   244 	int found_r_al;
   246 	assert(handle != NULL && str != NULL && found != NULL);
   248 	TRACE(("idn_nameprep_isvalidbidi(ctx=%s, str=\"%s\")\n",
   249 	       handle->version, idn__debug_ucs4xstring(str, 50)));
   251 	if (*str == '\0') {
   252 		*found = NULL;
   253 		return (idn_success);
   254 	}
   256 	/*
   257 	 * check first character's type and initialize variables.
   258 	 */
   259 	found_r_al = 0;
   260 	if (*str > UCS_MAX) {
   261 		/* This cannot happen, but just in case.. */
   262 		return (idn_invalid_codepoint);
   263 	} else if (*str > UNICODE_MAX) {
   264 		/* It is invalid.. */
   265 		*found = str;
   266 		return (idn_success);
   267 	}
   268 	first_char = last_char = (*(handle->biditype_proc))(*str);
   269 	if (first_char == idn_biditype_r_al) {
   270 		found_r_al = 1;
   271 	}
   272 	str++;
   274 	/*
   275 	 * see whether string is valid or not.
   276 	 */
   277 	while (*str != '\0') {
   278 		v = *str;
   280 		if (v > UCS_MAX) {
   281 			/* This cannot happen, but just in case.. */
   282 			return (idn_invalid_codepoint);
   283 		} else if (v > UNICODE_MAX) {
   284 			/* It is invalid.. */
   285 			*found = str;
   286 			return (idn_success);
   287 		} else { 
   288 			last_char = (*(handle->biditype_proc))(v);
   289 			if (found_r_al && last_char == idn_biditype_l) {
   290 				*found = str;
   291 				return (idn_success);
   292 			}
   293 			if (first_char != idn_biditype_r_al && last_char == idn_biditype_r_al) {
   294 				*found = str;
   295 				return (idn_success);
   296 			}
   297 			if (last_char == idn_biditype_r_al) {
   298 				found_r_al = 1;
   299 			}
   300 		}
   301 		str++;
   302 	}
   304 	if (found_r_al) {
   305 		if (last_char != idn_biditype_r_al) {
   306 			*found = str - 1;
   307 			return (idn_success);
   308 		}
   309 	}
   311 	*found = NULL;
   312 	return (idn_success);
   313 }
   315 idn_result_t
   316 idn_nameprep_createproc(const char *parameter, void **handlep) {
   317 	return idn_nameprep_create(parameter, (idn_nameprep_t *)handlep);
   318 }
   320 void
   321 idn_nameprep_destroyproc(void *handle) {
   322 	idn_nameprep_destroy((idn_nameprep_t)handle);
   323 }
   325 idn_result_t
   326 idn_nameprep_mapproc(void *handle, const uint32_t *from,
   327 		      uint32_t *to, size_t tolen) {
   328 	return idn_nameprep_map((idn_nameprep_t)handle, from, to, tolen);
   329 }
   331 idn_result_t
   332 idn_nameprep_prohibitproc(void *handle, const uint32_t *str,
   333 			   const uint32_t **found) {
   334 	return idn_nameprep_isprohibited((idn_nameprep_t)handle, str, found);
   335 }
   337 idn_result_t
   338 idn_nameprep_unassignedproc(void *handle, const uint32_t *str,
   339 			     const uint32_t **found) {
   340 	return idn_nameprep_isunassigned((idn_nameprep_t)handle, str, found);
   341 }
   343 idn_result_t
   344 idn_nameprep_bidiproc(void *handle, const uint32_t *str,
   345 		      const uint32_t **found) {
   346 	return idn_nameprep_isvalidbidi((idn_nameprep_t)handle, str, found);
   347 }

mercurial