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

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

	TRACE(("idn_decodename2(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_decodename2(default_conf, actions, from, to, tolen,
				auxencoding);

ret:
	if (r == idn_success) {
		TRACE(("idn_decodename2(): success (to=\"%s\")\n",
		       idn__debug_xstring(to, 50)));
	} else {
		TRACE(("idn_decodename2(): %s\n", idn_result_tostring(r)));
	}
	return (r);
}
Example #2
0
/*
 * Add an alias to 'ctx'.
 */
idn_result_t
idn__langalias_add(idn__langalias_t ctx, const char *alias_name,
		   const char *real_name) {
	idn_result_t r = idn_success;
	idn__langalias_entry_t new_entry = NULL;

	assert(ctx != NULL && alias_name != NULL && real_name != NULL);

	TRACE(("idn__langalias_add(alias=\"%s\", real=\"%s\")\n",
	       idn__debug_xstring(alias_name), idn__debug_xstring(real_name)));

	new_entry = (idn__langalias_entry_t)malloc(sizeof(*new_entry));
	if (new_entry == NULL) {
		r = idn_nomemory;
		goto ret;
	}
	new_entry->alias_name = NULL;
	new_entry->real_name  = NULL;
	new_entry->next       = NULL;

	new_entry->alias_name = idn__util_strdup(alias_name);
	if (new_entry->alias_name == NULL) {
		r = idn_nomemory;
		goto ret;
	}
	idn__util_asclower(new_entry->alias_name);

	new_entry->real_name = idn__util_strdup(real_name);
	if (new_entry->real_name == NULL) {
		r = idn_nomemory;
		goto ret;
	}
	idn__util_asclower(new_entry->real_name);

	r = idn__strhash8_put(ctx->hash, new_entry->alias_name,
			      new_entry->real_name);
	if (r != idn_success)
		goto ret;

	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:
	TRACE(("idn__langalias_add(): %s\n", idn_result_tostring(r)));
	if (r != idn_success) {
		if (new_entry != NULL) {
			free(new_entry->alias_name);
			free(new_entry->real_name);
			free(new_entry);
		}
	}
	return (r);
}
Example #3
0
idn_result_t
idn_converter_convtoucs4(idn_converter_t ctx, const char *from,
			 unsigned long *to, size_t tolen) {
	idn_result_t r;

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

	TRACE(("idn_converter_convtoucs4(ctx=%s, from=\"%s\", tolen=%d)\n",
	       ctx->local_encoding_name, idn__debug_xstring(from, 50),
	       (int)tolen));

	if (!ctx->opened_convtoucs4) {
		r = (*ctx->ops->opentoucs4)(ctx, &(ctx->private_data));
		if (r != idn_success)
			goto ret;
		ctx->opened_convtoucs4 = 1;
	}

	r = (*ctx->ops->convtoucs4)(ctx, ctx->private_data, from, to, tolen);
ret:
	if (r == idn_success) {
		TRACE(("idn_converter_convtoucs4(): success (to=\"%s\")\n",
		       idn__debug_ucs4xstring(to, 50)));
	} else {
		TRACE(("idn_converter_convtoucs4(): %s\n",
		       idn_result_tostring(r)));
	}
	return (r);
}
Example #4
0
/*
 * Find a real name for 'alias_name'.
 */
const char *
idn__langalias_find(idn__langalias_t ctx, const char *alias_name) {
	const char *real_name;
	const char *result;

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

	TRACE(("idn__langalias_find(alias=\"%s\")\n",
	       idn__debug_xstring(alias_name)));

	real_name = idn__strhash8_get(ctx->hash, alias_name);
	result = (real_name != NULL) ? real_name : alias_name;
	
	TRACE(("idn__langalias_find(): success (real=\"%s\")\n",
	       idn__debug_xstring(result)));
	return (result);
}
Example #5
0
idn_result_t
mdn_decodename(int 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(1)) != idn_success))
		return (r);

	return (idn_res_decodename(default_conf, actions, from, to, tolen));
}
Example #6
0
idn_result_t
idn_selectiveencode_findregion(const char *s,
			       char **startp, char **endp)
{
	char *non_ascii;
	char *start, *end;

	assert(s != NULL && startp != NULL && endp != NULL);

	TRACE(("idn_selectiveencode_findregion(s=\"%s\")\n",
	      idn__debug_xstring(s, 20)));

	/*
	 * Scan the specified string looking for non-ascii character.
	 */
	if ((non_ascii = find_nonascii(s)) == NULL)
		return (idn_notfound);

	/*
	 * Non-ascii character found.
	 * Determine the region to encode.
	 */
	
	/*
	 * First, we scan backwards to find the beginning of the region
	 * that should be converted.
	 */
	start = non_ascii;
	while (start > s) {
		char *prev = idn_utf8_findfirstbyte(start - 1, s);
		if (is_domain_delimiter(*prev))
			break;			/* Found */
		start = prev;
	}
	*startp = start;

	/*
	 * Next we scan forwards looking for the end of the region.
	 */
	end = non_ascii + idn_utf8_mblen(non_ascii);
	while (!is_domain_delimiter(*end))
		end += idn_utf8_mblen(end);
	*endp = end;

	return (idn_success);
}
Example #7
0
/*
 * Set the local encoding to 'name'.
 */
void
idn__localencoding_setname(idn__localencoding_t ctx, const char *name) {
	idn_result_t r = idn_success;

	assert(ctx != NULL);
	TRACE(("idn__localencoding_setname(name=\"%s\")\n",
		idn__debug_xstring(name)));

	if (name == NULL)
		ctx->is_static = 0;
	else {
		idn__util_strcpy(ctx->name, sizeof(ctx->name),
				 idn__encodingalias_find(aliases, name));
		ctx->is_static = 1;
	}

	TRACE(("idn__localencoding_setname(): %s\n", idn_result_tostring(r)));
}
Example #8
0
const char *
idn__localencoding_getname(idn__localencoding_t ctx) {
	const char *key = NULL;
#ifdef WIN32
	char cp_str[40];	/* enough */
#endif

	assert(ctx != NULL);
	TRACE(("idn__localencoding_getname()\n"));

	if (!ctx->is_static) {
		key = getenv(IDN_LOCALCS_ENV);
#ifdef WIN32
		if (key == NULL) {
			sprintf(cp_str, "CP%u", GetACP());
			key = cp_str;
		}
#endif
#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
		if (key == NULL)
			key = nl_langinfo(CODESET);
#endif
#ifdef HAVE_SETLOCALE
		if (key == NULL)
			key = setlocale(LC_CTYPE, NULL);
#endif
		if (key == NULL)
			key = getenv("LC_ALL");
		if (key == NULL)
			key = getenv("LC_CTYPE");
		if (key == NULL)
			key = getenv("LANG");
		if (key == NULL)
			key = getenv("LANG");
		if (key == NULL)
			key = IDN__UTF8_ENCODINGNAME;
		idn__util_strcpy(ctx->name, sizeof(ctx->name),
				 idn__encodingalias_find(aliases, key));
	}

	TRACE(("idn__localencoding_getname(): success "
	       "(name=\"%s\")\n", idn__debug_xstring(ctx->name)));
	return (ctx->name);
}
Example #9
0
/*
 * Perform UTF32 to UTF-8 to conversion.
 */
idn_result_t
idn__res_utf32toutf8(idn_resconf_t ctx, const unsigned long *from, char **to) {
	idn_result_t r = idn_success;
	size_t tolen = 0;

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

	TRACE(("idn__res_utf32toutf8(label=\"%s\")\n",
	       idn__debug_utf32xstring(from)));

	*to = NULL;
	tolen = 256;  /* may be large enough. */

	for (;;) {
		void *new_to;

		new_to = realloc(*to, sizeof(**to) * tolen);
		if (new_to == NULL) {
			r = idn_nomemory;
			goto ret;
		}
		*to = (char *)new_to;
		r = idn__utf32_toutf8(from, *to, tolen);
		if (r == idn_success)
			break;
		else if (r != idn_buffer_overflow)
			goto ret;
		tolen *= 2;
	}

ret:
	if (r == idn_success) {
		TRACE(("idn__res_utf32toutf8(): success (to=\"%s\")\n",
		       idn__debug_xstring(*to)));
	} else {
		TRACE(("idn__res_utf32toutf8(): %s\n",
		       idn_result_tostring(r)));
		free(*to);
		*to = NULL;
	}

	return (r);
}
Example #10
0
/*
 * Read an alias definition file and add aliases in it to 'ctx'.
 */
idn_result_t
idn__langalias_addfromfile(idn__langalias_t ctx, const char *file) {
	idn_result_t r = idn_success;
	FILE *fp = NULL;
	int line_no;
	char line[200], alias[200], real[200];

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

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

	fp = fopen(file, "r");
	if (fp == NULL) {
		r = idn_nofile;
		goto ret;
	}

	for (line_no = 1; fgets(line, sizeof(line), fp) != NULL; line_no++) {
		unsigned char *p = (unsigned char *)line;

		while (isascii(*p) && isspace(*p))
			p++;
		if (*p == '#' || *p == '\n' || *p == '\0')
			continue;
		if (sscanf((char *)p, "%s %s", alias, real) == 2) {
			r = idn__langalias_add(ctx, alias, real);
			if (r != idn_success)
				break;
		} else {
			INFO(("idn__langalias_addfromfile: syntax error, "
			      "line %d\n",line_no));
			r = idn_invalid_syntax;
			break;
		}
	}

ret:
	TRACE(("idn__langalias_addfromfile(): %s\n",
	       idn_result_tostring(r)));
	return (r);
}
Example #11
0
idn_result_t
idn_converter_convfromucs4(idn_converter_t ctx, const unsigned long *from,
			   char *to, size_t tolen) {
	idn_result_t r;

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

	TRACE(("idn_converter_convfromucs4(ctx=%s, from=\"%s\", tolen=%d)\n",
	       ctx->local_encoding_name, idn__debug_ucs4xstring(from, 50),
	       (int)tolen));

	if (!ctx->opened_convfromucs4) {
		r = (*ctx->ops->openfromucs4)(ctx, &(ctx->private_data));
		if (r != idn_success)
			goto ret;
		ctx->opened_convfromucs4 = 1;
	}

	r = (*ctx->ops->convfromucs4)(ctx, ctx->private_data, from, to, tolen);
	if (r != idn_success)
		goto ret;
	if ((ctx->flags & IDN_CONVERTER_RTCHECK) != 0) {
		r = roundtrip_check(ctx, from, to);
		if (r != idn_success)
			goto ret;
	}
	
	r = idn_success;
ret:
	if (r == idn_success) {
		TRACE(("idn_converter_convfromucs4(): success (to=\"%s\")\n",
		       idn__debug_xstring(to, 50)));
	} else {
		TRACE(("idn_converter_convfromucs4(): %s\n",
		       idn_result_tostring(r)));
	}
	return (r);
}
Example #12
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 #13
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 #14
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 #15
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 #16
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 #17
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 #18
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 #19
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 #20
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);
}