Example #1
0
idn_result_t
idn_decodename(idn_action_t actions, const char *from, char *to, size_t tolen) {
	idn_result_t r;

	assert(from != NULL && to != NULL);

	TRACE(("idn_decodename(actions=%s, from=\"%s\", tolen=%d)\n",
	       idn__res_actionstostring(actions),
	       idn__debug_xstring(from, 50), (int)tolen));

	if (!initialized && ((r = idn_nameinit(0)) != idn_success))
		goto ret;

	r = idn_res_decodename(default_conf, actions, from, to, tolen);

ret:
	if (r == idn_success) {
		TRACE(("idn_decodename(): success (to=\"%s\")\n",
		       idn__debug_xstring(to, 50)));
	} else {
		TRACE(("idn_decodename(): %s\n", idn_result_tostring(r)));
	}
	return (r);
}
Example #2
0
static idn_result_t
parse_idn_encoding(idn_resconf_t ctx, char *args, int lineno) {
	idn_result_t r;
	char *argv[MAX_CONF_LINE_ARGS + 1];
	int argc;

	argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);

	if (argc != 1) {
		ERROR(("libidnkit: wrong # of args for idn-encoding, "
		       "line %d\n", lineno));
		return (idn_invalid_syntax);
	}

	r = idn_converter_create(argv[0], &ctx->idn_converter,
				 IDN_CONVERTER_DELAYEDOPEN |
				 IDN_CONVERTER_RTCHECK);
	if (r != idn_success) {
		ERROR(("libidnkit: cannot create idn converter, %s, "
		       "line %d\n", idn_result_tostring(r), lineno));
	}

	return (r);
}
Example #3
0
static idn_result_t
label_asccheck(idn_resconf_t ctx, labellist_t label) {
	const unsigned long *name, *n;
	idn_result_t r;

	name = labellist_getname(label);
	TRACE(("res asccheck(label=\"%s\")\n",
	       idn__debug_ucs4xstring(name, 50)));

	if (*name == '-') {
		r = idn_prohibited;
		goto ret;
	}

	for (n = name; *n != '\0'; n++) {
		if (*n <= '\177') {
			if ((*n < '0' || *n > '9') &&
			    (*n < 'A' || *n > 'Z') &&
			    (*n < 'a' || *n > 'z') &&
			    *n != '-') {
				r  = idn_prohibited;
				goto ret;
			}
		}
	}

	if (n > name && *(n - 1) == '-') {
		r  = idn_prohibited;
		goto ret;
	}

	r = idn_success;
ret:	
	TRACE(("res asccheck(): %s\n", idn_result_tostring(r)));
	return (r);
}
Example #4
0
idn_result_t
idn_normalizer_normalize(idn_normalizer_t ctx, const unsigned long *from,
			 unsigned long *to, size_t tolen) {
	idn_result_t r;
	unsigned long *src, *dst;
	unsigned long *buffers[2] = {NULL, NULL};
	size_t buflen[2] = {0, 0};
	size_t dstlen;
	int idx;
	int i;

	assert(scheme_hash != NULL);
	assert(ctx != NULL && from != NULL && to != NULL);

	TRACE(("idn_normalizer_normalize(from=\"%s\", tolen=%d)\n",
	       idn__debug_ucs4xstring(from, 50), (int)tolen));

	if (ctx->nschemes <= 0) {
		if (tolen < idn_ucs4_strlen(from) + 1) {
			r = idn_buffer_overflow;
			goto ret;
		}
		idn_ucs4_strcpy(to, from);
		r = idn_success;
		goto ret;
	}

	/*
	 * Normalize.
	 */
	src = (void *)from;
	dstlen = idn_ucs4_strlen(from) + 1;

	i = 0;
	while (i < ctx->nschemes) {
		TRACE(("idn_normalizer_normalize(): normalize %s\n",
		       ctx->schemes[i]->name));

		/*
		 * Choose destination area to restore the result of a mapping.
		 */
		if (i + 1 == ctx->nschemes) {
			dst = to;
			dstlen = tolen;
		} else {
			if (src == buffers[0])
				idx = 1;
			else
				idx = 0;

			if (buflen[idx] < dstlen) {
				void *newbuf;

				newbuf = realloc(buffers[idx],
						 sizeof(long) * dstlen);
				if (newbuf == NULL) {
					r = idn_nomemory;
					goto ret;
				}
				buffers[idx] = (unsigned long *)newbuf;
				buflen[idx] = dstlen;
			}

			dst = buffers[idx];
			dstlen = buflen[idx];
		}

		/*
		 * Perform i-th normalization scheme.
		 * If buffer size is not enough, we double it and try again.
		 */
		r = (ctx->schemes[i]->proc)(src, dst, dstlen);
		if (r == idn_buffer_overflow && dst != to) {
			dstlen *= 2;
			continue;
		}
		if (r != idn_success)
			goto ret;

		src = dst;
		i++;
	}

	r = idn_success;
ret:
	free(buffers[0]);
	free(buffers[1]);
	if (r == idn_success) {
		TRACE(("idn_normalizer_normalize(): success (to=\"%s\")\n",
		       idn__debug_ucs4xstring(to, 50)));
	} else {
		TRACE(("idn_normalizer_normalize(): %s\n",
		       idn_result_tostring(r)));
	}
	return (r);
}
Example #5
0
static idn_result_t
roundtrip_check(idn_converter_t ctx, const unsigned long *from, const char *to)
{
	/*
	 * One problem with iconv() convertion is that
	 * iconv() doesn't signal an error if the input
	 * string contains characters which are valid but
	 * do not have mapping to the output codeset.
	 * (the behavior of iconv() for that case is defined as
	 * `implementation dependent')
	 * One way to check this case is to perform round-trip
	 * conversion and see if it is same as the original string.
	 */
	idn_result_t r;
	unsigned long *back;
	unsigned long backbuf[256];
	size_t fromlen;
	size_t backlen;

	TRACE(("idn_converter_convert: round-trip checking (from=\"%s\")\n",
	       idn__debug_ucs4xstring(from, 50)));

	/* Allocate enough buffer. */
	fromlen = idn_ucs4_strlen(from) + 1;
	if (fromlen * sizeof(*back) <= sizeof(backbuf)) {
		backlen = sizeof(backbuf);
		back = backbuf;
	} else {
		backlen = fromlen;
		back = (unsigned long *)malloc(backlen * sizeof(*back));
		if (back == NULL)
			return (idn_nomemory);
	}

	/*
	 * Perform backward conversion.
	 */
	r = idn_converter_convtoucs4(ctx, to, back, backlen);
	switch (r) {
	case idn_success:
		if (memcmp(back, from, sizeof(*from) * fromlen) != 0)
			r = idn_nomapping;
		break;
	case idn_invalid_encoding:
	case idn_buffer_overflow:
		r = idn_nomapping;
		break;
	default:
		break;
	}

	if (back != backbuf)
		free(back);

	if (r != idn_success) {
		TRACE(("round-trip check failed: %s\n",
		       idn_result_tostring(r)));
	}

	return (r);
}
Example #6
0
idn_result_t
idn_converter_create(const char *name, idn_converter_t *ctxp, int flags) {
	const char *realname;
	idn_converter_t ctx;
	idn_result_t r;
	void *v;

	assert(name != NULL && ctxp != NULL);

	TRACE(("idn_converter_create(%s)\n", name));

	realname = idn_converter_getrealname(name);
#ifdef DEBUG
	if (strcmp(name, realname) != 0) {
		TRACE(("idn_converter_create: realname=%s\n", realname));
	}
#endif

	*ctxp = NULL;

	/* Allocate memory for a converter context and the name. */
	ctx = malloc(sizeof(struct idn_converter) + strlen(realname) + 1);
	if (ctx == NULL) {
		r = idn_nomemory;
		goto ret;
	}

	ctx->local_encoding_name = (char *)(ctx + 1);
	(void)strcpy(ctx->local_encoding_name, realname);
	ctx->flags = flags;
	ctx->reference_count = 1;
	ctx->opened_convfromucs4 = 0;
	ctx->opened_convtoucs4 = 0;
	ctx->private_data = NULL;

	assert(encoding_name_hash != NULL);

	if (strcmp(realname, IDN_UTF8_ENCODING_NAME) == 0) {
		/* No conversion needed */
		ctx->ops = &none_converter_ops;
	} else if ((r = idn__strhash_get(encoding_name_hash, realname, &v))
		   == idn_success) {
		/* Special converter found */
		ctx->ops = (converter_ops_t *)v;
	} else {
		/* General case */
#ifdef WITHOUT_ICONV
		free(ctx);
		*ctxp = NULL;
		r = idn_invalid_name;
		goto ret;
#else
		ctx->ops = &iconv_converter_ops;
#endif
	}

	if ((flags & IDN_CONVERTER_DELAYEDOPEN) == 0) {
		r = (ctx->ops->openfromucs4)(ctx, &(ctx->private_data));
		if (r != idn_success) {
			WARNING(("idn_converter_create(): open failed "
			     "(ucs4->local)\n"));
			free(ctx);
			*ctxp = NULL;
			goto ret;
		}
		ctx->opened_convfromucs4 = 1;

		r = (*ctx->ops->opentoucs4)(ctx, &(ctx->private_data));
		if (r != idn_success) {
			WARNING(("idn_converter_create(): open failed "
			     "(local->ucs4)\n"));
			free(ctx);
			*ctxp = NULL;
			goto ret;
		}
		ctx->opened_convtoucs4 = 1;
	}

	*ctxp = ctx;
	r = idn_success;
ret:
	TRACE(("idn_converter_create(): %s\n", idn_result_tostring(r)));
	return (r);
}
Example #7
0
static idn_result_t
converter_uescape_convtoucs4(idn_converter_t ctx, void *privdata,
			const char *from, unsigned long *to, size_t tolen)
{
	idn_result_t r;
	size_t fromlen = strlen(from);

	while (*from != '\0') {
		if (tolen <= 0) {
			r = idn_buffer_overflow;
			goto failure;
		}
		if (strncmp(from, "\\u{", 3) == 0 ||
		    strncmp(from, "\\U{", 3) == 0) {
			size_t ullen;
			unsigned long v;
			char *end;

			v = strtoul(from + 3, &end, 16);
			ullen = end - (from + 3);
			if (*end == '}' && ullen > 1 && ullen < 8) {
				*to = v;
				from = end + 1;
				fromlen -= ullen;
			} else {
				*to = '\\';
				from++;
				fromlen--;
			}
		} else {
			int c = *(unsigned char *)from;
			size_t width;
			char buf[8];

			if (c < 0x80)
				width = 1;
			else if (c < 0xc0)
				width = 0;
			else if (c < 0xe0)
				width = 2;
			else if (c < 0xf0)
				width = 3;
			else if (c < 0xf8)
				width = 4;
			else if (c < 0xfc)
				width = 5;
			else if (c < 0xfe)
				width = 6;
			else
				width = 0;
			if (width == 0 || width > fromlen) {
				r = idn_invalid_encoding;
				goto failure;
			}

			memcpy(buf, from, width);
			buf[width] = '\0';
			r = idn_ucs4_utf8toucs4(buf, to, tolen);
			if (r != idn_success) {
				r = idn_invalid_encoding;
				goto failure;
			}
			from += width;
			fromlen -= width;
		}
		to++;
		tolen--;
	}

	if (tolen <= 0) {
		r = idn_buffer_overflow;
		goto failure;
	}
	*to = '\0';

	return (idn_success);

failure:
	if (r != idn_buffer_overflow) {
		WARNING(("idn_uescape_convtoucs4(): %s\n",
			 idn_result_tostring(r)));
	}
	return (r);
}
Example #8
0
idn_result_t
idn__race_decode(idn_converter_t ctx, void *privdata, 
		 const char *from, unsigned long *to, size_t tolen) {
	unsigned short *buf = NULL;
	size_t prefixlen = strlen(IDN_RACE_PREFIX);
	size_t fromlen;
	size_t buflen;
	idn_result_t r;

	assert(ctx != NULL);

	TRACE(("idn__race_decode(from=\"%s\", tolen=%d)\n",
	       idn__debug_xstring(from, 50), (int)tolen));

	if (!idn__util_asciihaveaceprefix(from, IDN_RACE_PREFIX)) {
		if (*from == '\0') {
			r = idn_ucs4_utf8toucs4(from, to, tolen);
			goto ret;
		}
		r = idn_invalid_encoding;
		goto ret;
	}
	from += prefixlen;
	fromlen = strlen(from);

	/*
	 * Allocate sufficient buffer.
	 */
	buflen = fromlen + 1;
	buf = malloc(sizeof(*buf) * buflen);
	if (buf == NULL) {
		r = idn_nomemory;
		goto ret;
	}

	/*
	 * Decode base32 and decompress.
	 */
	r = race_decode_decompress(from, buf, buflen);
	if (r != idn_success)
		goto ret;

	/*
	 * Now 'buf' points the decompressed string, which must contain
	 * UTF-16 characters.
	 */

	/*
	 * Convert to UCS4.
	 */
	r = idn_ucs4_utf16toucs4(buf, to, tolen);
	if (r != idn_success)
		goto ret;

ret:
	free(buf);
	if (r == idn_success) {
		TRACE(("idn__race_decode(): succcess (to=\"%s\")\n",
		       idn__debug_ucs4xstring(to, 50)));
	} else {
		TRACE(("idn__race_decode(): %s\n", idn_result_tostring(r)));
	}
	return (r);
}
Example #9
0
idn_result_t
idn_delimitermap_map(idn_delimitermap_t ctx, const unsigned long *from, 
		     unsigned long *to, size_t tolen) {

	/* default delimiters (label separators) from IDNA specification */
	static const unsigned long default_delimiters[] =
		{ 0x002e, /* full stop */
		  0x3002, /* ideographic full stop */
		  0xff0e, /* fullwidth full stop */
		  0xff61, /* halfwidth ideographic full stop */
		  0x0000 };

	unsigned long *to_org = to;
	idn_result_t r;
	int i, j;
	int found;

	assert(ctx != NULL && from != NULL && to != NULL);

	TRACE(("idn_delimitermap_map(from=\"%s\", tolen=%d)\n",
		idn__debug_ucs4xstring(from, 50), (int)tolen));

	/*
	 * Map.
	 */
	while (*from != '\0') {
		found = 0;
		if (tolen < 1) {
			r = idn_buffer_overflow;
			goto ret;
		}
		for (j = 0; default_delimiters[j] != 0x0000; j++) {
			if (default_delimiters[j] == *from) {
				found = 1;
				break;
			}
		}
		if (!found) {
			for (i = 0; i < ctx->ndelimiters; i++) {
				if (ctx->delimiters[i] == *from) {
					found = 1;
					break;
				}
			}
		}
		if (found)
			*to = '.';
		else
			*to = *from;
		from++;	
		to++;
		tolen--;
	}

	if (tolen < 1) {
		r = idn_buffer_overflow;
		goto ret;
	}
	*to = '\0';
	r = idn_success;

ret:
	if (r == idn_success) {
		TRACE(("idn_delimitermap_map(): success (to=\"%s\")\n",
		       idn__debug_ucs4xstring(to_org, 50)));
	} else {
		TRACE(("idn_delimitermap_map(): %s\n",
		       idn_result_tostring(r)));
	}
	return (r);
}
Example #10
0
idn_result_t
idn__punycode_encode(idn_converter_t ctx, void *privdata,
		    const unsigned long *from, char *to, size_t tolen) {
	char *to_org = to;
	unsigned long cur_code, next_code, delta;
	size_t prefixlen = strlen(IDN_PUNYCODE_PREFIX);
	size_t fromlen;
	size_t ucsdone;
	size_t toidx;
	int uidx, bias, first;
	idn_result_t r;

	assert(ctx != NULL);

	TRACE(("idn__punycode_encode(from=\"%s\", tolen=%d)\n",
	       idn__debug_ucs4xstring(from, 50), (int)tolen));

	if (*from == '\0') {
		r = idn_ucs4_ucs4toutf8(from, to, tolen);
		goto ret;
	} else if (idn__util_ucs4haveaceprefix(from, IDN_PUNYCODE_PREFIX)) {
		r = idn_prohibited;
		goto ret;
	}

	if (tolen < prefixlen) {
		r = idn_buffer_overflow;
		goto ret;
	}
	memcpy(to, IDN_PUNYCODE_PREFIX, prefixlen);
	to += prefixlen;
	tolen -= prefixlen;

	fromlen = idn_ucs4_strlen(from);

	/*
	 * If the input string is too long (actually too long to be sane),
	 * return failure in order to prevent possible overflow.
	 */
	if (fromlen > PUNYCODE_MAXINPUT) {
		ERROR(("idn__punycode_encode(): "
		       "the input string is too long to convert Punycode\n",
		       idn__debug_ucs4xstring(from, 50)));
		r = idn_failure;
		goto ret;
	}

	ucsdone = 0;	/* number of characters processed */
	toidx = 0;

	/*
	 * First, pick up basic code points and copy them to 'to'.
	 */
	for (uidx = 0; uidx < fromlen; uidx++) {
		if (from[uidx] < 0x80) {
			if (toidx >= tolen) {
				r = idn_buffer_overflow;
				goto ret;
			}
			to[toidx++] = from[uidx];
			ucsdone++;
		}
	}

	/*
	 * If there are any basic code points, output a delimiter
	 * (hyphen-minus).
	 */
	if (toidx > 0) {
		if (toidx >= tolen) {
			r = idn_buffer_overflow;
			goto ret;
		}
		to[toidx++] = '-';
		to += toidx;
		tolen -= toidx;
	}

	/*
	 * Then encode non-basic characters.
	 */
	first = 1;
	cur_code = PUNYCODE_INITIAL_N;
	bias = PUNYCODE_INITIAL_BIAS;
	delta = 0;
	while (ucsdone < fromlen) {
		int limit = -1, rest;

		/*
		 * Find the smallest code point equal to or greater
		 * than 'cur_code'.  Also remember the index of the
		 * last occurence of the code point.
		 */
		for (next_code = MAX_UCS, uidx = fromlen - 1;
		     uidx >= 0; uidx--) {
			if (from[uidx] >= cur_code && from[uidx] < next_code) {
				next_code = from[uidx];
				limit = uidx;
			}
		}
		/* There must be such code point. */
		assert(limit >= 0);

		delta += (next_code - cur_code) * (ucsdone + 1);
		cur_code = next_code;

		/*
		 * Scan the input string again, and encode characters
		 * whose code point is 'cur_code'.  Use 'limit' to avoid
		 * unnecessary scan.
		 */
		for (uidx = 0, rest = ucsdone; uidx <= limit; uidx++) {
			if (from[uidx] < cur_code) {
				delta++;
				rest--;
			} else if (from[uidx] == cur_code) {
				int sz = punycode_putwc(to, tolen, delta, bias);
				if (sz == 0) {
					r = idn_buffer_overflow;
					goto ret;
				}
				to += sz;
				tolen -= sz;
				ucsdone++;
				bias = punycode_update_bias(delta, ucsdone,
							   first);
				delta = 0;
				first = 0;
			}
		}
		delta += rest + 1;
		cur_code++;
	}

	/*
	 * Terminate with NUL.
	 */
	if (tolen <= 0) {
		r = idn_buffer_overflow;
		goto ret;
	}
	*to = '\0';
	r = idn_success;

ret:
	if (r == idn_success) {
		TRACE(("idn__punycode_encode(): succcess (to=\"%s\")\n",
		       idn__debug_xstring(to_org, 50)));
	} else {
		TRACE(("idn__punycode_encode(): %s\n", idn_result_tostring(r)));
	}
	return (r);
}
Example #11
0
idn_result_t
idn_checker_add(idn_checker_t ctx, const char *scheme_name) {
	idn_result_t r;
	check_scheme_t *scheme;
	const char *scheme_prefix;
	const char *scheme_parameter;
	void *scheme_context = NULL;
	char *buffer = NULL;

	assert(scheme_hash != NULL);
	assert(ctx != NULL);

	TRACE(("idn_checker_add(scheme_name=%s)\n",
		idn__debug_xstring(scheme_name, 50)));

	/*
	 * Split `scheme_name' into `scheme_prefix' and `scheme_parameter'.
	 */
	scheme_parameter = strchr(scheme_name, ':');
	if (scheme_parameter == NULL) {
		scheme_prefix = scheme_name;
		scheme_parameter = NULL;
	} else {
		ptrdiff_t scheme_prefixlen;

		scheme_prefixlen = scheme_parameter - scheme_name;
		buffer = (char *) malloc(scheme_prefixlen + 1);
		if (buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		memcpy(buffer, scheme_name, scheme_prefixlen);
		*(buffer + scheme_prefixlen) = '\0';
		scheme_prefix = buffer;
		scheme_parameter++;
	}

	/*
	 * Find a scheme.
	 */
	if (idn__strhash_get(scheme_hash, scheme_prefix, (void **)&scheme)
		!= idn_success) {
		ERROR(("idn_checker_add(): invalid scheme \"%-.30s\"\n",
		       scheme_name));
		r = idn_invalid_name;
		goto ret;
	}
	if (scheme_parameter == NULL && scheme->parameter != NULL)
		scheme_parameter = scheme->parameter;

	/*
	 * Add the scheme.
	 */
	assert(ctx->nschemes <= ctx->scheme_size);

	if (ctx->nschemes == ctx->scheme_size) {
		check_scheme_t *new_schemes;

		new_schemes = (check_scheme_t *) realloc(ctx->schemes,
			sizeof(check_scheme_t) * ctx->scheme_size * 2);
		if (new_schemes == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		ctx->schemes = new_schemes;
		ctx->scheme_size *= 2;
	}

	r = scheme->create(scheme_parameter, &scheme_context);
	if (r != idn_success)
		goto ret;

	memcpy(ctx->schemes + ctx->nschemes, scheme, sizeof(check_scheme_t));
	ctx->schemes[ctx->nschemes].context = scheme_context;
	ctx->nschemes++;
	r = idn_success;

ret:
	free(buffer);
	if (r != idn_success)
		free(scheme_context);
	TRACE(("idn_checker_add(): %s\n", idn_result_tostring(r)));
	return (r);
}
Example #12
0
idn_result_t
idn_res_decodename2(idn_resconf_t ctx, idn_action_t actions, const char *from,
		    char *to, size_t tolen, const char *auxencoding) {
#ifdef WITHOUT_ICONV
	return idn_failure;

#else /* WITHOUT_ICONV */
	idn_result_t r;
	idn_converter_t aux_converter = NULL;
	unsigned long *buffer_ucs4 = NULL;
	char *buffer_utf8 = NULL;
	size_t buffer_length;

	assert(ctx != NULL && from != NULL && to != NULL);

	TRACE(("idn_res_decodename2(actions=%s, from=\"%s\", tolen=%d, "
		"auxencoding=\"%s\")\n",
		idn__res_actionstostring(actions),
		idn__debug_xstring(from, 50), (int)tolen,
		(auxencoding != NULL) ? auxencoding : "<null>"));

	if (!initialized)
		idn_res_initialize();
	if (!enabled || actions == 0) {
		r = copy_verbatim(from, to, tolen);
		goto ret;
	} else if (tolen <= 0) {
		r = idn_buffer_overflow;
		goto ret;
	}

	if (auxencoding == NULL ||
	    strcmp(auxencoding, IDN_UTF8_ENCODING_NAME) == 0 ||
	    strcmp(auxencoding, "UTF-8") == 0) {
		return idn_res_decodename(ctx, actions, from, to, tolen);
	}

	/*
	 * Convert `from' to UCS4.
	 */
	r = idn_resconf_setauxidnconvertername(ctx, auxencoding,
					       IDN_CONVERTER_DELAYEDOPEN);
	if (r != idn_success) {
		goto ret;
	}

	aux_converter = idn_resconf_getauxidnconverter(ctx);
	if (aux_converter == NULL) {
		r = idn_failure;
		goto ret;
	}

	buffer_length = tolen * 2;
	for (;;) {
		void *new_buffer;

		new_buffer = realloc(buffer_ucs4,
				     sizeof(*buffer_ucs4) * buffer_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		buffer_ucs4 = (unsigned long *)new_buffer;

		r = idn_converter_convtoucs4(aux_converter, from,
					     buffer_ucs4,
					     buffer_length);
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;

		buffer_length *= 2;
	}

	if (*buffer_ucs4 == '\0') {
		if (tolen <= 0) {
			r = idn_buffer_overflow;
			goto ret;
		}
		*to = '\0';
		r = idn_success;
		goto ret;
	}

	/*
	 * Convert `buffer_ucs4' to UTF-8.
	 */
	buffer_length = tolen * 2;
	for (;;) {
		void *new_buffer;

		new_buffer = realloc(buffer_utf8,
				     sizeof(*buffer_utf8) * buffer_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		buffer_utf8 = (char *)new_buffer;
		r = idn_ucs4_ucs4toutf8(buffer_ucs4, buffer_utf8,
					buffer_length);

		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;

		buffer_length *= 2;
	}
	
	if (*buffer_utf8 == '\0') {
		if (tolen <= 0) {
			r = idn_buffer_overflow;
			goto ret;
		}
		*to = '\0';
		r = idn_success;
		goto ret;
	}

	r = idn_res_decodename(ctx, actions, buffer_utf8, to, tolen);

ret:
	if (r == idn_success) {
		TRACE(("idn_res_decodename2(): success (to=\"%s\")\n",
		       idn__debug_xstring(to, 50)));
	} else {
		TRACE(("idn_res_decodename2(): %s\n", idn_result_tostring(r)));
	}
	free(buffer_ucs4);
	free(buffer_utf8);
	if (aux_converter != NULL)
		idn_converter_destroy(aux_converter);

	return (r);

#endif /* WITHOUT_ICONV */
}
Example #13
0
idn_result_t
idn_res_decodename(idn_resconf_t ctx, idn_action_t actions, const char *from,
		    char *to, size_t tolen) {
	idn_converter_t local_converter = NULL;
	idn_converter_t idn_converter = NULL;
	idn_delimitermap_t delimiter_mapper;
	idn_result_t r;
	labellist_t labels = NULL, l;
	unsigned long *buffer = NULL;
	unsigned long *saved_name = NULL;
	size_t buffer_length;
	int idn_is_ace;

	assert(ctx != NULL && from != NULL && to != NULL);

	TRACE(("idn_res_decodename(actions=%s, from=\"%s\", tolen=%d)\n",
		idn__res_actionstostring(actions),
		idn__debug_xstring(from, 50), (int)tolen));

	if (actions & ~DECODE_MASK) {
		WARNING(("idn_res_decodename: invalid actions 0x%x\n",
			 actions));
		r = idn_invalid_action;
		goto ret;
	}

	if (!initialized)
		idn_res_initialize();
	if (!enabled || actions == 0) {
		r = copy_verbatim(from, to, tolen);
		goto ret;
	} else if (tolen <= 0) {
		r = idn_buffer_overflow;
		goto ret;
	}

	if (actions & IDN_DECODE_QUERY) {
#ifndef WITHOUT_ICONV
		actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \
			    IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \
			    IDN_RTCHECK | IDN_LOCALCONV);
#else
		actions |= (IDN_DELIMMAP | IDN_MAP | IDN_NORMALIZE | \
			    IDN_PROHCHECK | IDN_BIDICHECK | IDN_IDNCONV | \
			    IDN_RTCHECK);
#endif
	}

	/*
	 * Convert `from' to UCS4.
	 */
	local_converter = idn_resconf_getlocalconverter(ctx);
#ifndef WITHOUT_ICONV
	if (local_converter == NULL) {
		r = idn_invalid_name;
		goto ret;
	}
#endif

	idn_converter = idn_resconf_getidnconverter(ctx);
	if (idn_converter != NULL &&
	    idn_converter_isasciicompatible(idn_converter))
		idn_is_ace = 1;
	else
		idn_is_ace = 0;

	buffer_length = tolen * 2;

	TRACE(("res idndecode(name=\"%s\")\n", idn__debug_xstring(from, 50)));

	for (;;) {
		void *new_buffer;

		new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		buffer = (unsigned long *)new_buffer;

		if ((actions & IDN_IDNCONV) &&
		     idn_converter != NULL && !idn_is_ace) {
			r = idn_converter_convtoucs4(idn_converter, from,
						     buffer, buffer_length);
		} else {
			r = idn_ucs4_utf8toucs4(from, buffer, buffer_length);
		}
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;

		buffer_length *= 2;
	}

	if (*buffer == '\0') {
		if (tolen <= 0) {
			r = idn_buffer_overflow;
			goto ret;
		}
		*to = '\0';
		r = idn_success;
		goto ret;
	}

	/*
	 * Delimiter map.
	 */
	if (actions & IDN_DELIMMAP) {
		TRACE(("res delimitermap(name=\"%s\")\n",
		       idn__debug_ucs4xstring(buffer, 50)));

		delimiter_mapper = idn_resconf_getdelimitermap(ctx);
		if (delimiter_mapper != NULL) {
			r = idn_delimitermap_map(delimiter_mapper, buffer,
						 buffer, buffer_length);
			idn_delimitermap_destroy(delimiter_mapper);
			if (r != idn_success)
				goto ret;
		}
		TRACE(("res delimitermap(): success (name=\"%s\")\n",
		       idn__debug_ucs4xstring(buffer, 50)));
	}

	/*
	 * Split the name into a list of labels.
	 */
	r = labellist_create(buffer, &labels);
	if (r != idn_success)
		goto ret;

	/*
	 * Perform conversions and tests.
	 */
	for (l = labellist_tail(labels); l != NULL;
	     l = labellist_previous(l)) {

		free(saved_name);
		saved_name = NULL;

		if (!idn__util_ucs4isasciirange(labellist_getname(l))) {
			if (actions & IDN_MAP) {
				r = label_map(ctx, l);
				if (r != idn_success)
					goto ret;
			}
			if (actions & IDN_NORMALIZE) {
				r = label_normalize(ctx, l);
				if (r != idn_success)
					goto ret;
			}
			if (actions & IDN_PROHCHECK) {
				r = label_prohcheck(ctx, l);
				if (r == idn_prohibited) {
					labellist_undo(l);
					continue;
				} else if (r != idn_success) {
					goto ret;
				}
			}
			if (actions & IDN_UNASCHECK) {
				r = label_unascheck(ctx, l);
				if (r == idn_prohibited) {
					labellist_undo(l);
					continue;
				} else if (r != idn_success) {
					goto ret;
				}
			}
			if (actions & IDN_BIDICHECK) {
				r = label_bidicheck(ctx, l);
				if (r == idn_prohibited) {
					labellist_undo(l);
					continue;
				} else if (r != idn_success) {
					goto ret;
				}
			}
		}

		if ((actions & IDN_IDNCONV) && idn_is_ace) {
			saved_name = idn_ucs4_strdup(labellist_getname(l));
			if (saved_name == NULL) {
				r = idn_nomemory;
				goto ret;
			}
			r = label_idndecode(ctx, l);
			if (r == idn_invalid_encoding) {
				labellist_undo(l);
				continue;
			} else if (r != idn_success) {
				goto ret;
			}
		}
		if ((actions & IDN_RTCHECK) && saved_name != NULL) {
			r = label_rtcheck(ctx, actions, l, saved_name);
			if (r == idn_invalid_encoding) {
				labellist_undo(l);
				continue;
			} else if (r != idn_success) {
				goto ret;
			}
		}

#ifndef WITHOUT_ICONV
		if (actions & IDN_LOCALCONV) {
			r = label_localdecodecheck(ctx, l);
			if (r != idn_success)
				goto ret;
		}
#endif
	}

	/*
	 * Concat a list of labels to a name.
	 */
	for (;;) {
		void *new_buffer;

		new_buffer = realloc(buffer, sizeof(*buffer) * buffer_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		buffer = (unsigned long *)new_buffer;

		r = labellist_getnamelist(labels, buffer, buffer_length);
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;

		buffer_length *= 2;
	}

	if (actions & IDN_LOCALCONV) {
		r = idn_converter_convfromucs4(local_converter, buffer, to,
					       tolen);
	} else {
		r = idn_ucs4_ucs4toutf8(buffer, to, tolen);
	}

ret:
	if (r == idn_success) {
		TRACE(("idn_res_decodename(): success (to=\"%s\")\n",
		       idn__debug_xstring(to, 50)));
	} else {
		TRACE(("idn_res_decodename(): %s\n", idn_result_tostring(r)));
	}
	free(saved_name);
	free(buffer);
	if (local_converter != NULL)
		idn_converter_destroy(local_converter);
	if (idn_converter != NULL)
		idn_converter_destroy(idn_converter);
	if (labels != NULL)
		labellist_destroy(labels);
	return (r);
}
Example #14
0
static idn_result_t
label_rtcheck(idn_resconf_t ctx, idn_action_t actions, labellist_t label,
	    const unsigned long *original_name) {
	labellist_t rt_label = NULL;
	const unsigned long *rt_name;
	const unsigned long *cur_name;
	idn_result_t r;

	cur_name = labellist_getname(label);
	TRACE(("res rtcheck(label=\"%s\", org_label=\"%s\")\n",
		idn__debug_ucs4xstring(cur_name, 50),
		idn__debug_ucs4xstring(original_name, 50)));

	r = labellist_create(cur_name, &rt_label);
	if (r != idn_success)
		goto ret;
	if (rt_label == NULL) {
		if (*original_name == '\0')
			r = idn_success;
		else
			r = idn_invalid_encoding;
		goto ret;
	}

	if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
		r = label_map(ctx, rt_label);
		if (r != idn_success)
			goto ret;
		r = label_normalize(ctx, rt_label);
		if (r != idn_success)
			goto ret;
		r = label_prohcheck(ctx, rt_label);
		if (r != idn_success)
			goto ret;
		if (actions & IDN_UNASCHECK) {
			r = label_unascheck(ctx, rt_label);
			if (r != idn_success)
				goto ret;
		}
		r = label_bidicheck(ctx, rt_label);
		if (r != idn_success)
			goto ret;
	}

	if (actions & IDN_ASCCHECK) {
		r = label_asccheck(ctx, rt_label);
		if (r != idn_success)
			goto ret;
	}
	if (!idn__util_ucs4isasciirange(labellist_getname(rt_label))) {
		r = label_idnencode_ace(ctx, rt_label);
		if (r != idn_success)
			goto ret;
	}
	r = label_lencheck_ace(ctx, rt_label);
	if (r != idn_success)
		goto ret;
	rt_name = labellist_getname(rt_label);

	if (idn_ucs4_strcasecmp(rt_name, original_name) != 0) {
		TRACE(("res rtcheck(): round trip failed, org =\"%s\", rt=\"%s\"\n",
		       idn__debug_ucs4xstring(original_name, 50),
		       idn__debug_ucs4xstring(rt_name, 50)));
		r = idn_invalid_encoding;
		goto ret;
	}

	r  = idn_success;
ret:
	if (r != idn_nomemory && r != idn_success)
		r = idn_invalid_encoding;
	TRACE(("res rtcheck(): %s\n", idn_result_tostring(r)));
	if (rt_label != NULL)
		labellist_destroy(rt_label);
	return (r);
}
Example #15
0
static idn_result_t
label_idnencode_ace(idn_resconf_t ctx, labellist_t label) {
	idn_converter_t idn_converter = NULL;
	const unsigned long *from;
	char *ascii_to = NULL;
	unsigned long *to = NULL;
	size_t to_length;
	idn_result_t r;

	from = labellist_getname(label);
	TRACE(("res ucs4toidn(label=\"%s\")\n",
	       idn__debug_ucs4xstring(from, 50)));

	idn_converter = idn_resconf_getidnconverter(ctx);
	if (idn_converter == NULL) {
		r = idn_success;
		goto ret;
	}

	ascii_to = NULL;
	to_length = idn_ucs4_strlen(from) * 4 + 16;  /* add mergin */

	for (;;) {
		char *new_buffer;

		new_buffer = (char *) realloc(ascii_to, to_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		ascii_to = new_buffer;
		r = idn_converter_convfromucs4(idn_converter, from, ascii_to,
					       to_length);
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;
		to_length *= 2;
	}

	for (;;) {
		unsigned long *new_buffer;

		new_buffer = (unsigned long *)
			     realloc(to, sizeof(long) * to_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		to = new_buffer;
		r = idn_ucs4_utf8toucs4(ascii_to, to, to_length);
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;
		to_length *= 2;
	}

	if (r != idn_success)
		goto ret;

	r = labellist_setname(label, to);
ret:
	if (r == idn_success) {
		TRACE(("res ucs4toidn(): success (label=\"%s\")\n",
		       idn__debug_ucs4xstring(labellist_getname(label),
					      50)));
	} else {
		TRACE(("res ucs4toidn(): %s\n", idn_result_tostring(r)));
	}
	if (idn_converter != NULL)
		idn_converter_destroy(idn_converter);
	free(to);
	free(ascii_to);
	return (r);
}
Example #16
0
/*
 * Read a mapping definition file and add mappings in it to 'ctx'.
 */
idn_result_t
idn__tldlocalmap_addfromfile(idn__tldlocalmap_t ctx, const char *tld,
			     const char *file) {
	static const unsigned long default_map_tld[] = {
		'<', 'd', 'e', 'f', 'a', 'u', 'l', 't', '>', '\0'
	};
	idn_result_t r = idn_success;
	unsigned long tld_utf32[IDN__TLDLOCALMAP_MAXTLDLENGTH + 1];
	idn__tldlocalmap_entry_t new_entry = NULL;
	idn__foreignmap_t new_mapctx = NULL;

	assert(ctx != NULL && file != NULL);

	TRACE(("idn__tldlocalmap_addfromfile(tld=\"%s\", file=\"%s\")\n",
	       idn__debug_xstring(tld), idn__debug_xstring(file)));

	if (tld != NULL && *tld == '.')
		tld++;
	if (tld != NULL && *tld == '\0') {
		r = idn_invalid_syntax;
		goto ret;
	}
	if (tld != NULL && strcmp(tld, "*") == 0)
		tld = NULL;

	new_entry = (idn__tldlocalmap_entry_t)malloc(sizeof(*new_entry));
	if (new_entry == NULL) {
		r = idn_nomemory;
		goto ret;
	}
	new_entry->tld  = NULL;
	new_entry->map  = NULL;
	new_entry->next = NULL;

	r = idn__foreignmap_create(&new_mapctx);
	if (r != idn_success)
		goto ret;
	r = idn__foreignmap_addfromfile(new_mapctx, file);
	if (r != idn_success)
		goto ret;
	new_entry->map = new_mapctx;

	if (tld != NULL) {
		r = idn__utf32_fromutf8(tld, tld_utf32,
					IDN__TLDLOCALMAP_MAXTLDLENGTH + 1);
		if (r != idn_success) {
			r = idn_invalid_name;
			goto ret;
		}
		idn__utf32_asclower(tld_utf32);
		new_entry->tld = idn__utf32_strdup(tld_utf32);
		if (new_entry->tld == NULL) {
			r = idn_nomemory;
			goto ret;
		}

		r = idn__strhash32_put(ctx->hash, tld_utf32, new_entry);
		if (r != idn_success)
		goto ret;
	} else {
		new_entry->tld = idn__utf32_strdup(default_map_tld);
		if (new_entry->tld == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		ctx->default_map = new_entry;
	}

	if (ctx->entries_head == NULL) {
		ctx->entries_head = new_entry;
		ctx->entries_tail = new_entry;
	} else {
		ctx->entries_tail->next = new_entry;
		ctx->entries_tail = new_entry;
	}
	
ret:
	if (r == idn_success) {
		TRACE(("idn__tldlocalmap_addfromfile(): success "
		       "(tld=\"%s\")\n", idn__debug_xstring(tld)));
	} else {
		TRACE(("idn__tldlocalmap_addfromfile(): %s\n",
		       idn_result_tostring(r)));
		if (new_mapctx != NULL)
			idn__foreignmap_destroy(new_mapctx);
		if (new_entry != NULL) {
			free(new_entry->tld);
			free(new_entry);
		}
	}
	return (r);
}
Example #17
0
idn_result_t
idn_ucs4_utf8toucs4(const char *utf8, unsigned long *ucs4, size_t tolen) {
	const unsigned char *utf8p = (const unsigned char *)utf8;
	unsigned long *ucs4p = ucs4;
	unsigned long v, min;
	unsigned char c;
	int width;
	int i;
	idn_result_t r;

	TRACE(("idn_ucs4_utf8toucs4(utf8=\"%s\", tolen=%d)\n",
	       idn__debug_xstring(utf8, 50), (int)tolen));

	while(*utf8p != '\0') {
		c = *utf8p++;
		if (c < 0x80) {
			v = c;
			min = 0;
			width = 1;
		} else if (c < 0xc0) {
			WARNING(("idn_ucs4_utf8toucs4: invalid character\n"));
			r = idn_invalid_encoding;
			goto ret;
		} else if (c < 0xe0) {
			v = c & 0x1f;
			min = 0x80;
			width = 2;
		} else if (c < 0xf0) {
			v = c & 0x0f;
			min = 0x800;
			width = 3;
		} else if (c < 0xf8) {
			v = c & 0x07;
			min = 0x10000;
			width = 4;
		} else if (c < 0xfc) {
			v = c & 0x03;
			min = 0x200000;
			width = 5;
		} else if (c < 0xfe) {
			v = c & 0x01;
			min = 0x4000000;
			width = 6;
		} else {
			WARNING(("idn_ucs4_utf8toucs4: invalid character\n"));
			r = idn_invalid_encoding;
			goto ret;
		}

		for (i = width - 1; i > 0; i--) {
			c = *utf8p++;
			if (c < 0x80 || 0xc0 <= c) {
				WARNING(("idn_ucs4_utf8toucs4: "
					 "invalid character\n"));
				r = idn_invalid_encoding;
				goto ret;
			}
			v = (v << 6) | (c & 0x3f);
		}

	        if (v < min) {
			WARNING(("idn_ucs4_utf8toucs4: invalid character\n"));
			r = idn_invalid_encoding;
			goto ret;
		}
		if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
			WARNING(("idn_ucs4_utf8toucs4: UTF-8 string contains "
				 "surrogate pair\n"));
			r = idn_invalid_encoding;
			goto ret;
		}
		if (tolen < 1) {
			r = idn_buffer_overflow;
			goto ret;
		}
		tolen--;
		*ucs4p++ = v;
	}

	if (tolen < 1) {
		r = idn_buffer_overflow;
		goto ret;
	}
	*ucs4p = '\0';

	r = idn_success;
ret:
	if (r == idn_success) {
		TRACE(("idn_ucs4_utf8toucs4(): success (ucs4=\"%s\")\n",
		       idn__debug_ucs4xstring(ucs4, 50)));
	} else {
		TRACE(("idn_ucs4_utf8toucs4(): %s\n",
		       idn_result_tostring(r)));
	}
	return (r);
}
Example #18
0
static int decode_file (idn_resconf_t conf1, idn_resconf_t conf2, FILE * fp, int flags)
{
    idn_result_t r;

    idnconv_strbuf_t buf1, buf2;

    idn_action_t actions1, actions2;

    int nl_trimmed;

    int local_ace_hack, idn_ace_hack;

    idn_converter_t conv;

    /*
     * See if the input codeset is an ACE.
     */
    conv = idn_resconf_getidnconverter (conf1);
    if (conv != NULL && idn_converter_isasciicompatible (conv) && (flags & FLAG_SELECTIVE))
        idn_ace_hack = 1;
    else
        idn_ace_hack = 0;
    if (conv != NULL)
        idn_converter_destroy (conv);

    conv = idn_resconf_getlocalconverter (conf1);
    if (conv != NULL && idn_converter_isasciicompatible (conv) && (flags & FLAG_SELECTIVE))
        local_ace_hack = 1;
    else
        local_ace_hack = 0;
    if (conv != NULL)
        idn_converter_destroy (conv);

    actions1 = IDN_IDNCONV;

    if (local_ace_hack)
    {
        actions2 = IDN_IDNCONV;
        if (flags & FLAG_MAP)
            actions2 |= IDN_MAP;
        if (flags & FLAG_NORMALIZE)
            actions2 |= IDN_NORMALIZE;
        if (flags & FLAG_PROHIBITCHECK)
            actions2 |= IDN_PROHCHECK;
        if (flags & FLAG_UNASSIGNCHECK)
            actions2 |= IDN_UNASCHECK;
        if (flags & FLAG_BIDICHECK)
            actions2 |= IDN_BIDICHECK;
        if (flags & FLAG_ASCIICHECK)
            actions2 |= IDN_ASCCHECK;
        if (flags & FLAG_LENGTHCHECK)
            actions2 |= IDN_LENCHECK;
    }
    else
    {
        actions2 = IDN_LOCALCONV;
    }

    if (flags & FLAG_DELIMMAP)
        actions1 |= IDN_DELIMMAP;
    if (flags & FLAG_MAP)
        actions1 |= IDN_MAP;
    if (flags & FLAG_NORMALIZE)
        actions1 |= IDN_NORMALIZE;
    if (flags & FLAG_NORMALIZE)
        actions1 |= IDN_NORMALIZE;
    if (flags & FLAG_PROHIBITCHECK)
        actions1 |= IDN_PROHCHECK;
    if (flags & FLAG_UNASSIGNCHECK)
        actions1 |= IDN_UNASCHECK;
    if (flags & FLAG_BIDICHECK)
        actions1 |= IDN_BIDICHECK;
    if (flags & FLAG_ASCIICHECK)
        actions1 |= IDN_ASCCHECK;
    if (flags & FLAG_ROUNDTRIPCHECK)
        actions1 |= IDN_RTCHECK;

    strbuf_init (&buf1);
    strbuf_init (&buf2);
    line_number = 1;
    while (strbuf_getline (&buf1, fp) != NULL)
    {
        /*
         * Trim newline at the end.  This is needed for
         * those ascii-comatible encodings such as UTF-5 or RACE
         * not to try converting newlines, which will result
         * in `invalid encoding' error.
         */
        nl_trimmed = trim_newline (&buf1);

        /*
         * Treat input line as the string encoded in local
         * encoding and convert it to UTF-8 encoded string.
         */
        if (local_ace_hack)
        {
            if (strbuf_copy (&buf2, strbuf_get (&buf1)) == NULL)
                r = idn_nomemory;
            else
                r = idn_success;
        }
        else
        {
            r = convert_line (&buf1, &buf2, conf1, IDN_LOCALCONV, 0);
        }
        if (r != idn_success)
        {
            errormsg ("conversion failed at line %d: %s\n", line_number, idn_result_tostring (r));
            goto error;
        }

        /*
         * Convert internationalized domain names in the line.
         */
        if (idn_ace_hack)
        {
            r = convert_line (&buf2, &buf1, conf1, actions1, FLAG_REVERSE | FLAG_SELECTIVE);
        }
        else
        {
            r = convert_line (&buf2, &buf1, conf1, actions1, FLAG_REVERSE);
        }
        if (r != idn_success)
        {
            errormsg ("conversion failed at line %d: %s\n", line_number, idn_result_tostring (r));
            goto error;
        }
        if (!idn_utf8_isvalidstring (strbuf_get (&buf1)))
        {
            errormsg ("conversion to utf-8 failed at line %d\n", line_number);
            goto error;
        }

        /*
         * Perform round trip check and convert to the output
         * codeset.
         */
        if (local_ace_hack)
        {
            r = convert_line (&buf1, &buf2, conf2, actions2, FLAG_SELECTIVE);
        }
        else
        {
            r = convert_line (&buf1, &buf2, conf1, actions2, FLAG_REVERSE);
        }

        if (r != idn_success)
        {
            errormsg ("error in nameprep or output conversion "
                      "at line %d: %s\n", line_number, idn_result_tostring (r));
            goto error;
        }

        fputs (strbuf_get (&buf2), stdout);
        if (nl_trimmed)
            putc ('\n', stdout);

        if (flush_every_line)
            fflush (stdout);

        line_number++;
    }
    strbuf_reset (&buf1);
    strbuf_reset (&buf2);
    return (0);

  error:
    strbuf_reset (&buf1);
    strbuf_reset (&buf2);
    return (1);
}
Example #19
0
idn_result_t
idn__punycode_decode(idn_converter_t ctx, void *privdata,
		    const char *from, unsigned long *to, size_t tolen) {
	unsigned long *to_org = to;
	unsigned long c, idx;
	size_t prefixlen = strlen(IDN_PUNYCODE_PREFIX);
	size_t fromlen;
	size_t uidx, fidx, ucslen;
	int first, bias;
	idn_result_t r;

	assert(ctx != NULL);

	TRACE(("idn__punycode_decode(from=\"%s\", tolen=%d)\n",
	       idn__debug_xstring(from, 50), (int)tolen));

	if (!idn__util_asciihaveaceprefix(from, IDN_PUNYCODE_PREFIX)) {
		if (*from == '\0') {
			r = idn_ucs4_utf8toucs4(from, to, tolen);
			goto ret;
		}
		r = idn_invalid_encoding;
		goto ret;
	}
	from += prefixlen;
	fromlen = strlen(from);

	/*
	 * Find the last delimiter, and copy the characters
	 * before it verbatim.
	 */
	ucslen = 0;
	for (fidx = fromlen; fidx > 0; fidx--) {
		if (from[fidx - 1] == '-') {
			if (tolen < fidx) {
				r = idn_buffer_overflow;
				goto ret;
			}
			for (uidx = 0; uidx < fidx - 1; uidx++) {
				to[uidx] = from[uidx];
			}
			ucslen = uidx;
			break;
		}
	}

	first = 1;
	bias = PUNYCODE_INITIAL_BIAS;
	c = PUNYCODE_INITIAL_N;
	idx = 0;
	while (fidx < fromlen) {
		int len;
		unsigned long delta;
		int i;

		len = punycode_getwc(from + fidx, fromlen - fidx, bias, &delta);
		if (len == 0) {
			r = idn_invalid_encoding;
			goto ret;
		}
		fidx += len;

		bias = punycode_update_bias(delta, ucslen + 1, first);
		first = 0;
		idx += delta;
		c += idx / (ucslen + 1);
		uidx = idx % (ucslen + 1);

		/* Insert 'c' at uidx. */
		if (tolen-- <= 0) {
			r = idn_buffer_overflow;
			goto ret;
		}
		for (i = ucslen; i > uidx; i--)
			to[i] = to[i - 1];
		to[uidx] = c;

		ucslen++;
		idx = uidx + 1;
	}

	/* Terminate with NUL. */
	if (tolen <= 0) {
		r = idn_buffer_overflow;
		goto ret;
	}
	to[ucslen] = '\0';
	r = idn_success;

ret:
	if (r == idn_success) {
		TRACE(("idn__punycode_decode(): succcess (to=\"%s\")\n",
		       idn__debug_ucs4xstring(to_org, 50)));
	} else {
		TRACE(("idn__punycode_decode(): %s\n", idn_result_tostring(r)));
	}
	return (r);
}
Example #20
0
static idn_result_t
parse_nameprep(idn_resconf_t ctx, char *args, int lineno) {
	idn_result_t r;
	char *argv[MAX_CONF_LINE_ARGS + 1];
	char scheme_name[MAX_CONF_LINE_LENGTH + 1];
	int argc;

	argc = split_args(args, argv, MAX_CONF_LINE_ARGS + 1);

	if (argc != 1) {
		ERROR(("libidnkit: wrong # of args for nameprep, line %d\n",
		       lineno));
		return (idn_invalid_syntax);
	}

	/*
	 * Set mapper.
	 */
	r = idn_mapper_create(&ctx->mapper);
	if (r != idn_success) {
		ERROR(("libidnkit: cannot create mapper, %s, line %d\n",
		       idn_result_tostring(r), lineno));
		return (r);
	}

	r = idn_mapper_add(ctx->mapper, argv[0]);
	if (r == idn_invalid_name) {
		ERROR(("libidnkit: map scheme unavailable \"%-.30s\", "
		       "line %d\n", argv[0], lineno));
		return (r);
	} else if (r != idn_success) {
		return (r);
	}

	/*
	 * Set normalizer.
	 */
	r = idn_normalizer_create(&ctx->normalizer);
	if (r != idn_success) {
		ERROR(("libidnkit: cannot create normalizer, %s, line %d\n",
		       idn_result_tostring(r), lineno));
		return (r);
	}

	r = idn_normalizer_add(ctx->normalizer, argv[0]);
	if (r == idn_invalid_name) {
		ERROR(("libidnkit: unknown normalization scheme \"%-.30s\", "
		       "line %d\n", argv[0], lineno));
		return (r);
	} else if (r != idn_success) {
		return (r);
	}

	/*
	 * Set prohibit checker.
	 */
	r = idn_checker_create(&ctx->prohibit_checker);
	if (r != idn_success) {
		ERROR(("libidnkit: cannot create prohibit checker, %s, "
		       "line %d\n", idn_result_tostring(r), lineno));
		return (r);
	}

	sprintf(scheme_name, "%s%s", IDN_CHECKER_PROHIBIT_PREFIX, argv[0]);
	r = idn_checker_add(ctx->prohibit_checker, scheme_name);
	if (r == idn_invalid_name) {
		ERROR(("libidnkit: unknown prohibit scheme \"%-.30s\", "
		       "line %d\n", argv[0], lineno));
		return (r);
	} else if (r != idn_success) {
		return (r);
	}

	/*
	 * Set unassigned checker.
	 */
	r = idn_checker_create(&ctx->unassigned_checker);
	if (r != idn_success) {
		ERROR(("libidnkit: cannot create unassigned checker, %s, "
		       "line %d\n", idn_result_tostring(r), lineno));
		return (r);
	}

	sprintf(scheme_name, "%s%s", IDN_CHECKER_UNASSIGNED_PREFIX, argv[0]);
	r = idn_checker_add(ctx->unassigned_checker, scheme_name);
	if (r == idn_invalid_name) {
		ERROR(("libidnkit: unknown unassigned scheme \"%-.30s\", "
		       "line %d\n", argv[0], lineno));
		return (r);
	} else if (r != idn_success) {
		return (r);
	}

	/*
	 * Set bidi checker.
	 */
	r = idn_checker_create(&ctx->bidi_checker);
	if (r != idn_success) {
		ERROR(("libidnkit: cannot create bidi checker, %s, line %d\n",
		       idn_result_tostring(r), lineno));
		return (r);
	}

	sprintf(scheme_name, "%s%s", IDN_CHECKER_BIDI_PREFIX, argv[0]);
	r = idn_checker_add(ctx->bidi_checker, scheme_name);
	if (r == idn_invalid_name) {
		ERROR(("libidnkit: unknown bidi scheme \"%-.30s\", "
		       "line %d\n", argv[0], lineno));
		return (r);
	} else if (r != idn_success) {
		return (r);
	}

	return (idn_success);
}
Example #21
0
idn_result_t
selective_encode(idn_resconf_t conf, idn_action_t actions,
		 char *from, char *to, int tolen)
{
	for (;;) {
		int len;
		char *region_start, *region_end;
		idn_result_t r;
		char save;

		/*
		 * Find the region that needs conversion.
		 */
		r = idn_selectiveencode_findregion(from, &region_start,
						   &region_end);
		if (r == idn_notfound) {
			/*
			 * Not found.  Just copy the whole thing.
			 */
			if (tolen <= strlen(from))
				return (idn_buffer_overflow);
			(void)strcpy(to, from);
			return (idn_success);
		} else if (r != idn_success) {
			/* This should not happen.. */
			errormsg("internal error at line %d: %s\n",
				 line_number, idn_result_tostring(r));
			return (r);
		}

		/*
		 * We have found a region to convert.
		 * First, copy the prefix part verbatim.
		 */
		len = region_start - from;
		if (tolen < len) {
			errormsg("internal buffer overflow at line %d\n",
				 line_number);
			return (idn_buffer_overflow);
		}
		(void)memcpy(to, from, len);
		to += len;
		tolen -= len;

		/*
		 * Terminate the region with NUL.
		 */
		save = *region_end;
		*region_end = '\0';

		/*
		 * Encode the region.
		 */
		r = idn_res_encodename(conf, actions, region_start, to, tolen);

		/*
		 * Restore character.
		 */
		*region_end = save;

		if (r != idn_success)
			return (r);

		len = strlen(to);
		to += len;
		tolen -= len;

		from = region_end;
	}
}
Example #22
0
idn_result_t
idn_ucs4_ucs4toutf8(const unsigned long *ucs4, char *utf8, size_t tolen) {
	unsigned char *utf8p = (unsigned char *)utf8;
	unsigned long v;
	int width;
	int mask;
	int offset;
	idn_result_t r;

	TRACE(("idn_ucs4_ucs4toutf8(ucs4=\"%s\", tolen=%d)\n",
	       idn__debug_ucs4xstring(ucs4, 50), (int)tolen));

	while (*ucs4 != '\0') {
		v = *ucs4++;
		if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
			WARNING(("idn_ucs4_ucs4toutf8: UCS4 string contains "
				 "surrogate pair\n"));
			r = idn_invalid_encoding;
			goto ret;
		}
		if (v < 0x80) {
			mask = 0;
			width = 1;
		} else if (v < 0x800) {
			mask = 0xc0;
			width = 2;
		} else if (v < 0x10000) {
			mask = 0xe0;
			width = 3;
		} else if (v < 0x200000) {
			mask = 0xf0;
			width = 4;
		} else if (v < 0x4000000) {
			mask = 0xf8;
			width = 5;
		} else if (v < 0x80000000) {
			mask = 0xfc;
			width = 6;
		} else {
			WARNING(("idn_ucs4_ucs4toutf8: invalid character\n"));
			r = idn_invalid_encoding;
			goto ret;
		}

		if (tolen < width) {
			r = idn_buffer_overflow;
			goto ret;
		}
		offset = 6 * (width - 1);
		*utf8p++ = (v >> offset) | mask;
		mask = 0x80;
		while (offset > 0) {
			offset -= 6;
			*utf8p++ = ((v >> offset) & 0x3f) | mask;
		}
		tolen -= width;
	}

	if (tolen < 1) {
		r = idn_buffer_overflow;
		goto ret;
	}
	*utf8p = '\0';

	r = idn_success;
ret:
	if (r == idn_success) {
		TRACE(("idn_ucs4_ucs4toutf8(): success (utf8=\"%s\")\n",
		       idn__debug_xstring(utf8, 50)));
	} else {
		TRACE(("idn_ucs4_ucs4toutf8(): %s\n",
		       idn_result_tostring(r)));
	}
	return (r);
}
Example #23
0
int
main(int ac, char **av) {
	idn_result_t r;
	int exit_code = IDNCHECK_EXITCODE_SUCCESS;
	idncheck_option_t option;
	idn_action_t actions;
	idn_resconf_t resconf = NULL;

#ifdef HAVE_SETLOCALE
	setlocale(LC_ALL, "");
#endif

	/*
	 * Parse command line options.
	 */
	idncheck_option_init(&option);
	if (!parse_command_line(ac, av, &option)) {
		errormsg("try 'idncheck -help' for more information.\n");
		exit_code = IDNCHECK_EXITCODE_FAILURE;
		goto ret;
	}

	quiet_mode = option.quiet;

	/*
	 * Initialize idnkit library.
	 */
	r = idn_resconf_initialize();
	if (r != idn_success) {
		errormsg("error initializing library\n");
		exit_code = IDNCHECK_EXITCODE_FAILURE;
		goto ret;
	}

	/*
	 * Create a resource context.
	 */
	if (!create_resconf(&resconf, option.no_conf, option.conf_file, 
			    option.in_code, option.localcheck_file)) {
		exit_code = IDNCHECK_EXITCODE_FAILURE;
		goto ret;
	}

	/*
	 * Determine main actions.
	 */
	if (option.protocol == idncheck_registration)
		actions = IDN_CHECK_REGIST & ~option.skip_actions;
	else
		actions = IDN_CHECK_LOOKUP & ~option.skip_actions;
	if (option.localcheck_file != NULL &&
	    !(option.skip_actions & ~IDN_LOCALCHECK)) {
		actions |= IDN_LOCALCHECK;
	}

	/*
	 * Test mode.
	 */
	if (option.test) {
		print_test_status(resconf);
		goto ret;
	}

	/*
	 * Encode two names and compare them.
	 */
	r = idn_res_checkname(resconf, actions, option.name);

	if (r == idn_success) {
		errormsg("passed.\n");
	} else if (r == idn_prohcheck_error ||
		   r == idn_unascheck_error ||
		   r == idn_nfccheck_error ||
		   r == idn_prefcheck_error ||
		   r == idn_hyphcheck_error ||
		   r == idn_combcheck_error ||
		   r == idn_ctxjcheck_error ||
		   r == idn_ctxocheck_error ||
		   r == idn_bidicheck_error ||
		   r == idn_localcheck_error ||
		   r == idn_lencheck_error ||
		   r == idn_rtcheck_error ||
		   r == idn_tr46check_error) {
		errormsg("%s\n", idn_result_tostring(r));
		exit_code = IDNCHECK_EXITCODE_CHECKERROR;
	} else if (r != idn_success) {
		errormsg("%s\n", idn_result_tostring(r));
		exit_code = IDNCHECK_EXITCODE_FAILURE;
	} 

ret:
	if (resconf != NULL)
		idn_resconf_destroy(resconf);

	return (exit_code);
}