Example #1
0
static idn_result_t
converter_none_convfromucs4(idn_converter_t ctx, void *privdata,
		       const unsigned long *from, char *to, size_t tolen) {
	assert(ctx != NULL && from != NULL && to != NULL);

	return idn_ucs4_ucs4toutf8(from, to, tolen);
}
Example #2
0
static idn_result_t
label_lencheck_nonace(idn_resconf_t ctx, labellist_t label) {
	idn_converter_t idn_converter;
	const unsigned long *from;
	size_t to_length;
	idn_result_t r;
	char *buffer = NULL;
	size_t buffer_length;

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

	buffer_length = idn_ucs4_strlen(from) * 4 + 16; /* 16 for margin */
	idn_converter = idn_resconf_getidnconverter(ctx);

	for (;;) {
		void *new_buffer;

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

		if (idn_converter != NULL) {
			r = idn_converter_convfromucs4(idn_converter, from,
						       buffer, buffer_length);
		} else {
			r = idn_ucs4_ucs4toutf8(from, buffer, buffer_length);
		}
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;

		buffer_length *= 2;
	}

	to_length = strlen(buffer);
	if (to_length == 0 || to_length > MAX_LABEL_LENGTH) {
		r = idn_invalid_length;
		goto ret;
	}

	r = idn_success;
ret:
	TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
	if (idn_converter != NULL)
		idn_converter_destroy(idn_converter);
	free(buffer);
	return (r);
}
Example #3
0
static idn_result_t
converter_iconv_convfromucs4(idn_converter_t ctx, void *privdata,
			     const unsigned long *from, char *to,
			     size_t tolen) {
	iconv_t ictx;
	char *utf8 = NULL;
	size_t utf8size = 256;  /* large enough */
	idn_result_t r;
	size_t sz;
	size_t inleft;
	size_t outleft;
	char *inbuf, *outbuf;

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

	if (tolen <= 0) {
		r = idn_buffer_overflow;	/* need space for NUL */
		goto ret;
	}

	/*
	 * UCS4 -> UTF-8 conversion.
	 */
	utf8 = (char *)malloc(utf8size);
	if (utf8 == NULL) {
		r = idn_nomemory;
		goto ret;
	}

try_again:
	r = idn_ucs4_ucs4toutf8(from, utf8, utf8size);
	if (r == idn_buffer_overflow) {
		char *new_utf8;

		utf8size *= 2;
		new_utf8 = (char *)realloc(utf8, utf8size);
		if (new_utf8 == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		utf8 = new_utf8;
		goto try_again;
	} else if (r != idn_success) {
		goto ret;
	}

	ictx = ((iconv_t *)privdata)[0];

	/*
	 * Reset internal state.
	 * 
	 * The following code should work according to the SUSv2 spec,
	 * but causes segmentation fault with Solaris 2.6.
	 * So.. a work-around.
	 * 
	 * (void)iconv(ictx, (const char **)NULL, (size_t *)NULL, 
	 * 	    (char **)NULL, (size_t *)NULL);
	 */
	inleft = 0;
	outbuf = NULL;
	outleft = 0;
	(void)iconv(ictx, (const char **)NULL, &inleft, &outbuf, &outleft);

	inleft = strlen(utf8);
	inbuf = utf8;
	outleft = tolen - 1;	/* reserve space for terminating NUL */
	sz = iconv(ictx, (const char **)&inbuf, &inleft, &to, &outleft);

	if (sz == (size_t)(-1) || inleft > 0) {
		switch (errno) {
		case EILSEQ:
		case EINVAL:
			/*
			 * We already checked the validity of the input
			 * string.  So we assume a mapping error.
			 */
			r = idn_nomapping;
			goto ret;
		case E2BIG:
			r = idn_buffer_overflow;
			goto ret;
		default:
			WARNING(("iconv failed with errno %d\n", errno));
			r = idn_failure;
			goto ret;
		}
	}

	/*
	 * For UTF-8 -> local conversion, append a sequence of
	 * state reset.
	 */
	inleft = 0;
	sz = iconv(ictx, (const char **)NULL, &inleft, &to, &outleft);
	if (sz == (size_t)(-1)) {
		switch (errno) {
		case EILSEQ:
		case EINVAL:
			r = idn_invalid_encoding;
			goto ret;
		case E2BIG:
			r = idn_buffer_overflow;
			goto ret;
		default:
			WARNING(("iconv failed with errno %d\n", errno));
			r = idn_failure;
			goto ret;
		}
	}
	*to = '\0';
	r = idn_success;

ret:
	free(utf8);
	return (r);

}
Example #4
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 #5
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 #6
0
static idn_result_t
label_idndecode(idn_resconf_t ctx, labellist_t label) {
	idn_converter_t idn_converter = NULL;
	const unsigned long *from;
	char *ascii_from = NULL;
	unsigned long *to = NULL;
	size_t from_length, to_length;
	idn_result_t r;

	from = labellist_getname(label);
	from_length = idn_ucs4_strlen(from) + 1;
	TRACE(("res idntoucs4(label=\"%s\")\n",
	       idn__debug_ucs4xstring(from, 50)));

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

	for (;;) {
		char *new_buffer;

		new_buffer = (char *) realloc(ascii_from, from_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		ascii_from = new_buffer;
		r = idn_ucs4_ucs4toutf8(from, ascii_from, from_length);
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;
		from_length *= 2;
	}

	to = NULL;
	to_length = from_length;

	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_converter_convtoucs4(idn_converter, ascii_from, to,
					     to_length);
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;
		to_length *= 2;
	}

	r = labellist_setname(label, to);
ret:
	if (r == idn_success) {
		TRACE(("res idntoucs4(): success (label=\"%s\")\n",
		       idn__debug_ucs4xstring(labellist_getname(label),
					      50)));
	} else {
		TRACE(("res idntoucs4(): %s\n", idn_result_tostring(r)));
	}
	if (idn_converter != NULL)
		idn_converter_destroy(idn_converter);
	free(to);
	free(ascii_from);
	return (r);
}
Example #7
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);
}