Exemple #1
0
void
idn_testsuite_assertucs4string(idn_testsuite_t ctx,
                               const unsigned long *gotten,
                               const unsigned long *expected,
                               const char *file, int lineno) {
    char *expected_hex = NULL;
    char *gotten_hex = NULL;
    char *msg;

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

    if (idn_testsuite_getstatus(ctx) != idn_teststatus_pass)
        return;
    if (idn_ucs4_strcmp(expected, gotten) == 0)
        return;
    idn_testsuite_setstatus(ctx, idn_teststatus_fail);

    msg = (char *)malloc(idn_ucs4_strlen(expected) * 8 +
                         idn_ucs4_strlen(gotten) * 8 + 32);
    expected_hex = make_hex_ucs4string(expected);
    gotten_hex = make_hex_ucs4string(gotten);
    if (msg == NULL || expected_hex == NULL || gotten_hex == NULL) {
        msg = "";
    } else {
        sprintf(msg, "`%s' expected, but got `%s'",
                expected_hex, gotten_hex);
    }

    put_failure_message(ctx, msg, file, lineno);

    free(msg);
    free(expected_hex);
    free(gotten_hex);
}
Exemple #2
0
static void
labellist_undo(labellist_t label) {
	size_t length;

	length = idn_ucs4_strlen(label->undo_name) + 1;
	memcpy(label->name, label->undo_name, sizeof(long) * length);
}
Exemple #3
0
static idn_result_t
label_localmap(idn_resconf_t ctx, labellist_t label) {
	const unsigned long *from;
	const unsigned long *tld;
	unsigned long *to = NULL;
	size_t to_length;
	idn_mapselector_t local_mapper;
	idn_result_t r;

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

	local_mapper = idn_resconf_getlocalmapselector(ctx);
	if (local_mapper == NULL) {
		r = idn_success;
		goto ret;
	}

	if (tld == from)
		tld = idn_mapselector_getdefaulttld();
	to_length = idn_ucs4_strlen(from) + 1 + 15;  /* 15 for margin */

	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_mapselector_map2(local_mapper, from, tld, 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 localmap(): success (label=\"%s\")\n",
		       idn__debug_ucs4xstring(labellist_getname(label),
					      50)));
	} else {
		TRACE(("res localmap(): %s\n", idn_result_tostring(r)));
	}
	if (local_mapper != NULL)
		idn_mapselector_destroy(local_mapper);
	free(to);
	return (r);
}
Exemple #4
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);
}
Exemple #5
0
unsigned long *
idn_ucs4_strdup(const unsigned long *str) {
	size_t length = idn_ucs4_strlen(str);
	unsigned long *dupstr;

	dupstr = (unsigned long *)malloc(sizeof(*str) * (length + 1));
	if (dupstr == NULL)
		return NULL;
	memcpy(dupstr, str, sizeof(*str) * (length + 1));

	return dupstr;
}
Exemple #6
0
static idn_result_t
label_normalize(idn_resconf_t ctx, labellist_t label) {
	const unsigned long *from;
	unsigned long *to = NULL;
	size_t to_length;
	idn_normalizer_t normalizer;
	idn_result_t r;

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

	normalizer = idn_resconf_getnormalizer(ctx);
	if (normalizer == NULL) {
		r = idn_success;
		goto ret;
	}
	to_length = idn_ucs4_strlen(from) + 1 + 15;  /* 15 for margin */

	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_normalizer_normalize(normalizer, 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 normalize(): success (label=\"%s\")\n",
		       idn__debug_ucs4xstring(labellist_getname(label),
					      50)));
	} else {
		TRACE(("res normalize(): %s\n", idn_result_tostring(r)));
	}
	if (normalizer != NULL)
		idn_normalizer_destroy(normalizer);
	free(to);
	return (r);
}
Exemple #7
0
static idn_result_t
label_localdecodecheck(idn_resconf_t ctx, labellist_t label) {
	idn_converter_t local_converter = NULL;
	const unsigned long *from;
	char *to = NULL;
	size_t to_length;
	idn_result_t r;

	from = labellist_getname(label);
	to_length = idn_ucs4_strlen(from) + 1 + 15;  /* 15 for margin */
	TRACE(("res ucs4tolocal_check(label=\"%s\")\n",
	       idn__debug_ucs4xstring(from, 50)));

	local_converter = idn_resconf_getlocalconverter(ctx);
	if (local_converter == NULL) {
		r = idn_success;
		goto ret;
	}

	for (;;) {
		char *new_buffer;

		new_buffer = (char *)realloc(to, to_length);
		if (new_buffer == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		to = new_buffer;
		r = idn_converter_convfromucs4(local_converter, from, to,
					       to_length);
		if (r == idn_success)
			break;
		else if (r == idn_nomapping) {
			r = label_idnencode_ace(ctx, label);
			if (r != idn_success)
				goto ret;
			break;
		} else if (r != idn_buffer_overflow) {
			goto ret;
		}
		to_length *= 2;
	}

	r = idn_success;
ret:
	TRACE(("res ucs4tolocal_check(): %s\n", idn_result_tostring(r)));
	if (local_converter != NULL)
		idn_converter_destroy(local_converter);
	free(to);
	return (r);
}
Exemple #8
0
static idn_result_t
labellist_getnamelist(labellist_t label, unsigned long *name,
			  size_t name_length) {
	static const unsigned long dot_string[] = {0x002e, 0x0000};  /* "." */
	size_t length;
	labellist_t l;

	for (l = label, length = 0; l != NULL; l = l->next)
		length += idn_ucs4_strlen(l->name) + 1;  /* name + `.' */
	length++;  /* for NUL */

	if (name_length < length)
		return (idn_buffer_overflow);

	*name = '\0';
	for (l = label; l != NULL; l = l->next) {
		idn_ucs4_strcat(name, l->name);
		name += idn_ucs4_strlen(name);
		if (l->dot_followed)
			idn_ucs4_strcat(name, dot_string);
	}
	return (idn_success);
}
Exemple #9
0
static idn_result_t
labellist_setname(labellist_t label, const unsigned long *name) {
	unsigned long *new_name;
	size_t length, new_length;

	length = idn_ucs4_strlen(name) + 1;
	new_length = length + 15;  /* add 15 for margin */

	if (label->name_length < new_length) {
		new_name = (unsigned long *)
			   realloc(label->name, sizeof(long) * new_length);
		if (new_name == NULL)
			return (idn_nomemory);
		label->name = new_name;
		label->name_length = new_length;
	}
	memcpy(label->name, name, sizeof(long) * length);

	return (idn_success);
}
Exemple #10
0
static idn_result_t
label_lencheck_ace(idn_resconf_t ctx, labellist_t label) {
	const unsigned long *name;
	size_t name_length;
	idn_result_t r;

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

	if (name_length == 0 || name_length > MAX_LABEL_LENGTH) {
		r = idn_invalid_length;
		goto ret;
	}

	r = idn_success;
ret:	
	TRACE(("res lencheck(): %s\n", idn_result_tostring(r)));
	return (r);
}
Exemple #11
0
static char *
make_hex_ucs4string(const unsigned long *string) {
    static const char hex[] = {"0123456789abcdef"};
    char *hex_string;
    const unsigned long *src;
    char *dst;

    hex_string = (char *)malloc((idn_ucs4_strlen(string)) * 8 + 1);
    if (hex_string == NULL)
        return NULL;

    for (src = string, dst = hex_string; *src != '\0'; src++) {
        if (0x20 <= *src && *src <= 0x7e && *src != '\\') {
            *dst++ = *src;
        } else if (*src <= UCS4_MAX) {
            *dst++ = '\\';
            *dst++ = 'u';
            if (*src >= 0x100000) {
                *dst++ = hex[(*src >> 20) & 0x0f];
            }
            if (*src >= 0x10000) {
                *dst++ = hex[(*src >> 16) & 0x0f];
            }
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);
}
Exemple #13
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);
}
Exemple #14
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);
}
Exemple #15
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);
}