Switch IDNA implementation to libidn2 [BZ #19728] [BZ #19729] [BZ #22247]

This provides an implementation of the IDNA2008 standard and fixes
CVE-2016-6261, CVE-2016-6263, CVE-2017-14062.
This commit is contained in:
Florian Weimer 2018-05-23 15:26:19 +02:00
parent 5f7b841d3a
commit 7f9f1ecb71
44 changed files with 1351 additions and 19143 deletions

View File

@ -1,3 +1,67 @@
2018-05-23 Florian Weimer <fweimer@redhat.com>
[BZ #19728]
[BZ #19729]
[BZ #22247]
CVE-2016-6261
CVE-2016-6263
CVE-2017-14062
Switch to extern IDNA implementation (libidn2).
* libidn: Remove subdirectory.
* LICENSES: Do not mention licensing conditions for the removed
libidn code.
* config.h.in (HAVE_LIBIDN): Remove.
* include/dlfcn.h (__libc_dlopen): Update comment.
* include/idna.h: Remove file.
* inet/Makefile (routines): Add idna.
(tests-static, tests-internal): Add tst-idna_name_classify.
(LOCALES): Generate locales for tests.
(tst-idna_name_classify.out): Depend on generated locales.
* inet/idna_name_classify.c: New file.
* inet/tst-idna_name_classify.c: Likewise.
* inet/net-internal.h (__idna_to_dns_encoding)
(__idna_from_dns_encoding): Declare.
* inet/net-internal.h (enum idna_name_classification): Define.
(__idna_name_classify): Declare.
* inet/Versions (GLIBC_PRIVATE): Add __idna_to_dns_encoding,
__idna_from_dns_encoding.
* inet/getnameinfo.c (DEPRECATED_NI_IDN): Define.
(gni_host_inet_name): Call __idna_from_dns_encoding. Use punycode
name as a fallback in case of encoding errors.
(getnameinfo): Use DEPRECATED_NI_IDN.
* inet/idna.c: New file.
* nscd/gai.c: Do not include <libidn/idn-stub.c>.
* resolv/Makefile (tests): Add tst-resolv-ai_idn,
tst-resolv-ai_idn-latin1, tst-resolv-ai_idn-nolibidn2.
(modules-names): Add tst-no-libidn2.
(extra-test-objs): Add tst-no-libidn2.os.
(LDFLAGS-tst-no-libidn2.so): Set soname.
(LOCALES): Set, and generate locales.
(tst-resolv-ai_idn): Link with -ldl -lresolv -lpthread.
(tst-resolv-ai_idn-latin1): Likewise.
(tst-resolv-ai_idn-nolibidn2): Likewise.
(tst-resolv-ai_idn.out): Depend on locales.
(tst-resolv-ai_idn-latin1.out): Depend on locales.
(tst-resolv-ai_idn-nolibidn2.out): Depend on locales and
tst-no-libidn2.so.
* resolv/netdb.h (AI_IDN_ALLOW_UNASSIGNED)
(AI_IDN_USE_STD3_ASCII_RULES, NI_IDN_ALLOW_UNASSIGNED)
(NI_IDN_USE_STD3_ASCII_RULES): Deprecate.
* resolv/tst-resolv-ai_idn.c: New file.
* resolv/tst-resolv-ai_idn-latin1.c: Likewise.
* resolv/tst-resolv-ai_idn-nolibidn2.c: Likewise.
* resolv/tst-no-libidn2.c: Likewise.
* support/support_format_addrinfo.c (format_ai_flags): Do not
handle AI_IDN_ALLOW_UNASSIGNED, AI_IDN_USE_STD3_ASCII_RULES.
* sysdeps/posix/getaddrinfo.c (DEPRECATED_AI_IDN): Define.
(gaih_inet): Call __idna_to_dns_encoding and
__idna_from_dns_encoding, and use the original (punycode) name if
__idna_from_dns_encoding fails due to an encoding error.
(getaddrinfo): Use DEPRECATED_AI_IDN.
* sysdeps/unix/inet/Subdirs (libidn): Remove.
* sysdeps/unix/inet/configure: Remove file.
* sysdeps/unix/inet/configure.ac: Likewise.
2018-05-23 Florian Weimer <fweimer@redhat.com>
Implement allocate_once.

View File

@ -248,75 +248,6 @@ Public License, version 2.1 or later - see the file COPYING.LIB for details.
If you did not receive a copy of the license with this program, please
see <http://www.gnu.org/licenses/> to obtain a copy.
The libidn code is copyright Simon Josefsson, with portions copyright
The Internet Society, Tom Tromey and Red Hat, Inc.:
Copyright (C) 2002, 2003, 2004, 2011 Simon Josefsson
This file is part of GNU Libidn.
GNU Libidn is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
GNU Libidn is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
The following notice applies to portions of libidn/nfkc.c:
This file contains functions from GLIB, including gutf8.c and
gunidecomp.c, all licensed under LGPL and copyright hold by:
Copyright (C) 1999, 2000 Tom Tromey
Copyright 2000 Red Hat, Inc.
The following applies to portions of libidn/punycode.c and
libidn/punycode.h:
This file is derived from RFC 3492bis written by Adam M. Costello.
Disclaimer and license: Regarding this entire document or any
portion of it (including the pseudocode and C code), the author
makes no guarantees and is not responsible for any damage resulting
from its use. The author grants irrevocable permission to anyone
to use, modify, and distribute it in any way that does not diminish
the rights of anyone else to use, modify, and distribute it,
provided that redistributed derivative works do not contain
misleading author or version information. Derivative works need
not be licensed under similar terms.
Copyright (C) The Internet Society (2003). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
The file inet/rcmd.c is under a UCB copyright and the following:
Copyright (C) 1998 WIDE Project.

24
NEWS
View File

@ -31,6 +31,16 @@ Major new features:
* Building and running on GNU/Hurd systems now works without out-of-tree
patches.
* IDN domain names in getaddrinfo and getnameinfo now use the system libidn2
library if installed. libidn2 version 2.0.5 or later is recommended. If
libidn2 is not available, internationalized domain names are not encoded
or decoded even if the AI_IDN or NI_IDN flags are passed to getaddrinfo or
getnameinfo. (getaddrinfo calls with non-ASCII names and AI_IDN will fail
with an encoding error.) Flags which used to change the IDN encoding and
decoding behavior (AI_IDN_ALLOW_UNASSIGNED, AI_IDN_USE_STD3_ASCII_RULES,
NI_IDN_ALLOW_UNASSIGNED, NI_IDN_USE_STD3_ASCII_RULES) have been
deprecated. They no longer have any effect.
Deprecated and removed features, and other changes affecting compatibility:
* The nonstandard header files <libio.h> and <_G_config.h> are no longer
@ -79,13 +89,25 @@ Deprecated and removed features, and other changes affecting compatibility:
and was not declared in a header. Programs should use the lseek64 name
for this function instead.
* The AI_IDN_ALLOW_UNASSIGNED and NI_IDN_ALLOW_UNASSIGNED flags for the
getaddrinfo and getnameinfo functions have been deprecated. The behavior
previously selected by them is now always enabled.
* The AI_IDN_USE_STD3_ASCII_RULES and NI_IDN_USE_STD3_ASCII_RULES flags for
the getaddrinfo and getnameinfo functions have been deprecated. The STD3
restriction (rejecting '_' in host names, among other things) has been
removed, for increased compatibility with non-IDN name resolution.
Changes to build and runtime requirements:
[Add changes to build and runtime requirements here]
Security related changes:
[Add security related changes here]
CVE-2016-6261, CVE-2016-6263, CVE-2017-14062: Various vulnerabilities have
been fixed by removing the glibc-internal IDNA implementation and using
the system-provided libidn2 library instead. Originally reported by Hanno
Böck and Christian Weisgerber.
The following bugs are resolved with this release:

View File

@ -124,9 +124,6 @@
/* Mach/i386 specific: define if the `i386_set_gdt' RPC is available. */
#undef HAVE_I386_SET_GDT
/* Defined of libidn is available. */
#undef HAVE_LIBIDN
/* Define if inlined system calls are available. */
#undef HAVE_INLINED_SYSCALLS

View File

@ -46,7 +46,7 @@ extern char **__libc_argv attribute_hidden;
The use of RTLD_NOW also impacts gconv module loading, backtracing
(where the unwinder form libgcc_s.so is used), and IDNA functions
(which load libidn), all of which load their respective DSOs on
(which load libidn2), all of which load their respective DSOs on
demand, and so should not impact program startup. That is to say
that the DSOs are loaded as part of an API call and therefore we
will be calling that family of API functions shortly so RTLD_NOW or

View File

@ -1,8 +0,0 @@
#ifndef _IDNA_H
#include <libidn/idna.h>
extern __typeof (idna_to_ascii_lz) __idna_to_ascii_lz attribute_hidden;
extern __typeof (idna_to_unicode_lzlz ) __idna_to_unicode_lzlz
attribute_hidden;
#endif

View File

@ -45,7 +45,7 @@ routines := htonl htons \
in6_addr getnameinfo if_index ifaddrs inet6_option \
getipv4sourcefilter setipv4sourcefilter \
getsourcefilter setsourcefilter inet6_opt inet6_rth \
inet6_scopeid_pton deadline
inet6_scopeid_pton deadline idna idna_name_classify
aux := check_pf check_native ifreq
@ -59,12 +59,20 @@ tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
tests-static += tst-deadline
tests-internal += tst-deadline
# tst-idna_name_classify must be linked statically because it tests
# internal functionality.
tests-static += tst-idna_name_classify
tests-internal += tst-idna_name_classify
# tst-inet6_scopeid_pton also needs internal functions but does not
# need to be linked statically.
tests-internal += tst-inet6_scopeid_pton
include ../Rules
LOCALES := en_US.UTF-8 en_US.ISO-8859-1
include ../gen-locales.mk
ifeq ($(have-thread-library),yes)
CFLAGS-gethstbyad_r.c += -fexceptions
@ -103,3 +111,5 @@ endif
ifeq ($(build-static-nss),yes)
CFLAGS += -DSTATIC_NSS
endif
$(objpfx)tst-idna_name_classify.out: $(gen-locales)

View File

@ -88,5 +88,7 @@ libc {
# Used from nscd.
__inet6_scopeid_pton;
__idna_to_dns_encoding;
__idna_from_dns_encoding;
}
}

View File

@ -71,10 +71,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sys/utsname.h>
#include <libc-lock.h>
#include <scratch_buffer.h>
#ifdef HAVE_LIBIDN
# include <idna.h>
#endif
#include <net-internal.h>
#ifndef min
# define min(x,y) (((x) > (y)) ? (y) : (x))
@ -82,6 +79,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
libc_freeres_ptr (static char *domain);
/* Former NI_IDN_ALLOW_UNASSIGNED, NI_IDN_USE_STD3_ASCII_RULES flags,
now ignored. */
#define DEPRECATED_NI_IDN 192
static char *
nrl_domainname (void)
@ -285,41 +285,28 @@ gni_host_inet_name (struct scratch_buffer *tmpbuf,
/* Terminate the string after the prefix. */
*c = '\0';
#ifdef HAVE_LIBIDN
/* If requested, convert from the IDN format. */
if (flags & NI_IDN)
bool do_idn = flags & NI_IDN;
char *h_name;
if (do_idn)
{
int idn_flags = 0;
if (flags & NI_IDN_ALLOW_UNASSIGNED)
idn_flags |= IDNA_ALLOW_UNASSIGNED;
if (flags & NI_IDN_USE_STD3_ASCII_RULES)
idn_flags |= IDNA_USE_STD3_ASCII_RULES;
char *out;
int rc = __idna_to_unicode_lzlz (h->h_name, &out,
idn_flags);
if (rc != IDNA_SUCCESS)
{
if (rc == IDNA_MALLOC_ERROR)
return EAI_MEMORY;
if (rc == IDNA_DLOPEN_ERROR)
return EAI_SYSTEM;
return EAI_IDN_ENCODE;
int rc = __idna_from_dns_encoding (h->h_name, &h_name);
if (rc == EAI_IDN_ENCODE)
/* Use the punycode name as a fallback. */
do_idn = false;
else if (rc != 0)
return rc;
}
if (!do_idn)
h_name = h->h_name;
if (out != h->h_name)
{
h->h_name = strdupa (out);
free (out);
}
}
#endif
size_t len = strlen (h->h_name) + 1;
size_t len = strlen (h_name) + 1;
if (len > hostlen)
return EAI_OVERFLOW;
memcpy (host, h_name, len);
memcpy (host, h->h_name, len);
if (do_idn)
free (h_name);
return 0;
}
@ -501,10 +488,7 @@ getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
int flags)
{
if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM
#ifdef HAVE_LIBIDN
|NI_IDN|NI_IDN_ALLOW_UNASSIGNED|NI_IDN_USE_STD3_ASCII_RULES
#endif
))
|NI_IDN|DEPRECATED_NI_IDN))
return EAI_BADFLAGS;
if (sa == NULL || addrlen < sizeof (sa_family_t))

182
inet/idna.c Normal file
View File

@ -0,0 +1,182 @@
/* IDNA functions, forwarding to implementations in libidn2.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <allocate_once.h>
#include <dlfcn.h>
#include <inet/net-internal.h>
#include <netdb.h>
#include <stdbool.h>
/* Use the soname and version to locate libidn2, to ensure a
compatible ABI. */
#define LIBIDN2_SONAME "libidn2.so.0"
#define LIBIDN2_VERSION "IDN2_0.0.0"
/* Return codes from libidn2. */
enum
{
IDN2_OK = 0,
IDN2_MALLOC = -100,
};
/* Functions from libidn2. */
struct functions
{
void *handle;
int (*lookup_ul) (const char *src, char **result, int flags);
int (*to_unicode_lzlz) (const char *name, char **result, int flags);
};
static void *
functions_allocate (void *closure)
{
struct functions *result = malloc (sizeof (*result));
if (result == NULL)
return NULL;
void *handle = __libc_dlopen (LIBIDN2_SONAME);
if (handle == NULL)
/* Do not cache open failures. The library may appear
later. */
{
free (result);
return NULL;
}
void *ptr_lookup_ul
= __libc_dlvsym (handle, "idn2_lookup_ul", LIBIDN2_VERSION);
void *ptr_to_unicode_lzlz
= __libc_dlvsym (handle, "idn2_to_unicode_lzlz", LIBIDN2_VERSION);
if (ptr_lookup_ul == NULL || ptr_to_unicode_lzlz == NULL)
{
__libc_dlclose (handle);
free (result);
return NULL;
}
result->handle = handle;
result->lookup_ul = ptr_lookup_ul;
result->to_unicode_lzlz = ptr_to_unicode_lzlz;
#ifdef PTR_MANGLE
PTR_MANGLE (result->lookup_ul);
PTR_MANGLE (result->to_unicode_lzlz);
#endif
return result;
}
static void
functions_deallocate (void *closure, void *ptr)
{
struct functions *functions = ptr;
__libc_dlclose (functions->handle);
free (functions);
}
/* Ensure that *functions is initialized and return the value of the
pointer. If the library cannot be loaded, return NULL. */
static inline struct functions *
get_functions (void)
{
static void *functions;
return allocate_once (&functions, functions_allocate, functions_deallocate,
NULL);
}
/* strdup with an EAI_* error code. */
static int
gai_strdup (const char *name, char **result)
{
char *ptr = __strdup (name);
if (ptr == NULL)
return EAI_MEMORY;
*result = ptr;
return 0;
}
int
__idna_to_dns_encoding (const char *name, char **result)
{
switch (__idna_name_classify (name))
{
case idna_name_ascii:
/* Nothing to convert. */
return gai_strdup (name, result);
case idna_name_nonascii:
/* Encoding needed. Handled below. */
break;
case idna_name_nonascii_backslash:
case idna_name_encoding_error:
return EAI_IDN_ENCODE;
case idna_name_memory_error:
return EAI_MEMORY;
case idna_name_error:
return EAI_SYSTEM;
}
struct functions *functions = get_functions ();
if (functions == NULL)
/* We report this as an encoding error (assuming that libidn2 is
not installed), although the root cause may be a temporary
error condition due to resource shortage. */
return EAI_IDN_ENCODE;
char *ptr = NULL;
__typeof__ (functions->lookup_ul) fptr = functions->lookup_ul;
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (fptr);
#endif
int ret = fptr (name, &ptr, 0);
if (ret == 0)
{
/* Assume that idn2_free is equivalent to free. */
*result = ptr;
return 0;
}
else if (ret == IDN2_MALLOC)
return EAI_MEMORY;
else
return EAI_IDN_ENCODE;
}
libc_hidden_def (__idna_to_dns_encoding)
int
__idna_from_dns_encoding (const char *name, char **result)
{
struct functions *functions = get_functions ();
if (functions == NULL)
/* Simply use the encoded name, assuming that it is not punycode
(but even a punycode name would be syntactically valid). */
return gai_strdup (name, result);
char *ptr = NULL;
__typeof__ (functions->to_unicode_lzlz) fptr = functions->to_unicode_lzlz;
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (fptr);
#endif
int ret = fptr (name, &ptr, 0);
if (ret == 0)
{
/* Assume that idn2_free is equivalent to free. */
*result = ptr;
return 0;
}
else if (ret == IDN2_MALLOC)
return EAI_MEMORY;
else
return EAI_IDN_ENCODE;
}
libc_hidden_def (__idna_from_dns_encoding)

75
inet/idna_name_classify.c Normal file
View File

@ -0,0 +1,75 @@
/* Classify a domain name for IDNA purposes.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <inet/net-internal.h>
#include <stdbool.h>
#include <string.h>
#include <wchar.h>
enum idna_name_classification
__idna_name_classify (const char *name)
{
mbstate_t mbs;
memset (&mbs, 0, sizeof (mbs));
const char *p = name;
const char *end = p + strlen (p) + 1;
bool nonascii = false;
bool backslash = false;
while (true)
{
wchar_t wc;
size_t result = mbrtowc (&wc, p, end - p, &mbs);
if (result == 0)
/* NUL terminator was reached. */
break;
else if (result == (size_t) -2)
/* Incomplete trailing multi-byte character. This is an
encoding error becaue we received the full name. */
return idna_name_encoding_error;
else if (result == (size_t) -1)
{
/* Other error, including EILSEQ. */
if (errno == EILSEQ)
return idna_name_encoding_error;
else if (errno == ENOMEM)
return idna_name_memory_error;
else
return idna_name_error;
}
else
{
/* A wide character was decoded. */
p += result;
if (wc == L'\\')
backslash = true;
else if (wc > 127)
nonascii = true;
}
}
if (nonascii)
{
if (backslash)
return idna_name_nonascii_backslash;
else
return idna_name_nonascii;
}
else
return idna_name_ascii;
}

View File

@ -29,6 +29,33 @@ int __inet6_scopeid_pton (const struct in6_addr *address,
libc_hidden_proto (__inet6_scopeid_pton)
/* IDNA conversion. These functions convert domain names between the
current multi-byte character set and the IDNA encoding. On
success, the result string is written to *RESULT (which the caller
has to free), and zero is returned. On error, an EAI_* error code
is returned (see <netdb.h>), and *RESULT is not changed. */
int __idna_to_dns_encoding (const char *name, char **result);
libc_hidden_proto (__idna_to_dns_encoding)
int __idna_from_dns_encoding (const char *name, char **result);
libc_hidden_proto (__idna_from_dns_encoding)
/* Return value of __idna_name_classify below. */
enum idna_name_classification
{
idna_name_ascii, /* No non-ASCII characters. */
idna_name_nonascii, /* Non-ASCII characters, no backslash. */
idna_name_nonascii_backslash, /* Non-ASCII characters with backslash. */
idna_name_encoding_error, /* Decoding error. */
idna_name_memory_error, /* Memory allocation failure. */
idna_name_error, /* Other error during decoding. Check errno. */
};
/* Check the specified name for non-ASCII characters and backslashes
or encoding errors. */
enum idna_name_classification __idna_name_classify (const char *name)
attribute_hidden;
/* Deadline handling for enforcing timeouts.
Code should call __deadline_current_time to obtain the current time

View File

@ -0,0 +1,73 @@
/* Test IDNA name classification.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <inet/net-internal.h>
#include <locale.h>
#include <stdio.h>
#include <support/check.h>
static void
locale_insensitive_tests (void)
{
TEST_COMPARE (__idna_name_classify (""), idna_name_ascii);
TEST_COMPARE (__idna_name_classify ("abc"), idna_name_ascii);
TEST_COMPARE (__idna_name_classify (".."), idna_name_ascii);
TEST_COMPARE (__idna_name_classify ("\001abc\177"), idna_name_ascii);
TEST_COMPARE (__idna_name_classify ("\\065bc"), idna_name_ascii);
}
static int
do_test (void)
{
puts ("info: C locale tests");
locale_insensitive_tests ();
TEST_COMPARE (__idna_name_classify ("abc\200def"),
idna_name_encoding_error);
TEST_COMPARE (__idna_name_classify ("abc\200\\def"),
idna_name_encoding_error);
TEST_COMPARE (__idna_name_classify ("abc\377def"),
idna_name_encoding_error);
puts ("info: en_US.ISO-8859-1 locale tests");
if (setlocale (LC_CTYPE, "en_US.ISO-8859-1") == 0)
FAIL_EXIT1 ("setlocale for en_US.ISO-8859-1: %m\n");
locale_insensitive_tests ();
TEST_COMPARE (__idna_name_classify ("abc\200def"), idna_name_nonascii);
TEST_COMPARE (__idna_name_classify ("abc\377def"), idna_name_nonascii);
TEST_COMPARE (__idna_name_classify ("abc\\\200def"),
idna_name_nonascii_backslash);
TEST_COMPARE (__idna_name_classify ("abc\200\\def"),
idna_name_nonascii_backslash);
puts ("info: en_US.UTF-8 locale tests");
if (setlocale (LC_CTYPE, "en_US.UTF-8") == 0)
FAIL_EXIT1 ("setlocale for en_US.UTF-8: %m\n");
locale_insensitive_tests ();
TEST_COMPARE (__idna_name_classify ("abc\xc3\x9f""def"), idna_name_nonascii);
TEST_COMPARE (__idna_name_classify ("abc\\\xc3\x9f""def"),
idna_name_nonascii_backslash);
TEST_COMPARE (__idna_name_classify ("abc\xc3\x9f\\def"),
idna_name_nonascii_backslash);
TEST_COMPARE (__idna_name_classify ("abc\200def"), idna_name_encoding_error);
TEST_COMPARE (__idna_name_classify ("abc\xc3""def"), idna_name_encoding_error);
TEST_COMPARE (__idna_name_classify ("abc\xc3"), idna_name_encoding_error);
return 0;
}
#include <support/test-driver.c>

View File

@ -1,34 +0,0 @@
# Copyright (C) 2003-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# The GNU C Library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with the GNU C Library; if not, see
# <http://www.gnu.org/licenses/>.
# Makefile for libidn subdirectory of GNU C Library.
subdir := libidn
include ../Makeconfig
routines = idn-stub
extra-libs = libcidn
extra-libs-others = $(extra-libs)
libcidn-routines := punycode toutf8 nfkc stringprep rfc3454 profiles idna \
iconvme
libcidn-inhibit-o = $(filter-out .os,$(object-suffixes))
include $(..)Rules

View File

@ -1,6 +0,0 @@
libcidn {
GLIBC_PRIVATE {
idna_to_ascii_lz;
idna_to_unicode_lzlz;
}
}

View File

@ -1,658 +0,0 @@
#define COMPOSE_FIRST_START 1
#define COMPOSE_FIRST_SINGLE_START 147
#define COMPOSE_SECOND_START 357
#define COMPOSE_SECOND_SINGLE_START 388
#define COMPOSE_TABLE_LAST 48
static const guint16 compose_data[][256] = {
{ /* page 0, index 0 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 147, 148, 149, 0, 0, 1, 2, 3, 4, 5,
150, 6, 7, 8, 151, 9, 10, 11, 12, 13, 14, 0, 15, 16, 17, 18, 19, 20, 21,
22, 23, 0, 0, 0, 0, 0, 0, 24, 25, 26, 27, 28, 152, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 0, 39, 40, 41, 42, 43, 44, 45, 46, 47, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 153, 154,
50, 155, 0, 0, 51, 0, 0, 0, 0, 156, 0, 0, 0, 0, 52, 53, 157, 0, 158, 0,
0, 0, 54, 0, 0, 0, 0, 0, 55, 0, 159, 160, 56, 161, 0, 0, 57, 0, 0, 0, 0,
162, 0, 0, 0, 0, 58, 59, 163, 0, 164, 0, 0, 0, 60, 0, 0, 0
},
{ /* page 1, index 1 */
0, 0, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 64, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 65, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 166, 0,
0, 0, 0, 167, 168, 0, 0, 0, 0, 0, 0, 169, 170, 171, 172, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67,
68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 0, 0, 0, 0, 0, 0, 174,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 175, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0
},
{ /* page 2, index 2 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 177, 178, 179, 180, 0, 0, 0, 0,
181, 182, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 183, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 3, index 3 */
357, 358, 359, 360, 361, 0, 362, 363, 364, 365, 366, 367, 368, 0, 0, 369,
0, 370, 0, 371, 372, 0, 0, 0, 0, 0, 0, 373, 0, 0, 0, 0, 0, 0, 0, 374,
375, 376, 377, 378, 379, 0, 0, 0, 0, 380, 381, 0, 382, 383, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 0, 0, 385, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 0, 0, 0,
72, 0, 73, 0, 74, 0, 0, 0, 0, 0, 75, 0, 184, 0, 0, 0, 76, 0, 0, 0, 77, 0,
0, 185, 0, 186, 0, 0, 78, 0, 0, 0, 79, 0, 80, 0, 81, 0, 0, 0, 0, 0, 82,
0, 83, 0, 0, 0, 84, 0, 0, 0, 85, 86, 87, 0, 0, 187, 0, 0, 0, 88, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 4, index 4 */
0, 0, 0, 0, 0, 0, 188, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 0, 0, 189, 0, 90,
91, 190, 92, 0, 191, 0, 0, 0, 192, 0, 0, 0, 0, 93, 0, 0, 0, 193, 0, 0, 0,
194, 0, 195, 0, 0, 94, 0, 0, 196, 0, 95, 96, 197, 97, 0, 198, 0, 0, 0,
199, 0, 0, 0, 0, 98, 0, 0, 0, 200, 0, 0, 0, 201, 0, 202, 0, 0, 0, 0, 0,
0, 0, 0, 203, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 206, 207, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 208, 209, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 6, index 5 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
210, 0, 211, 0, 0, 0, 0, 0, 0, 0, 0, 388, 389, 390, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 212, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, 0,
0, 214, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 9, index 6 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, 0, 0,
216, 0, 0, 217, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 391,
0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
392, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 11, index 7 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 393, 0, 0, 0, 0, 0, 0, 0, 0,
101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 394, 395, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 218, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 396, 0, 0, 0, 0, 0, 0, 0, 102, 219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 12, index 8 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221,
0, 0, 398, 0, 0, 0, 103, 0, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 399,
400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 13, index 9 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 401, 0, 0, 0, 0, 0, 0, 0, 104,
223, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 402, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 403, 0, 0, 0, 0, 404, 0, 0, 0, 0, 0,
0, 0, 0, 0, 105, 0, 0, 224, 0, 0, 405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 16, index 10 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 30, index 11 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 226, 227, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 229, 0, 0,
0, 0, 0, 0, 230, 231, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 106, 107, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 233, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 234, 235, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 31, index 12 */
108, 109, 236, 237, 238, 239, 240, 241, 110, 111, 242, 243, 244, 245,
246, 247, 112, 113, 0, 0, 0, 0, 0, 0, 114, 115, 0, 0, 0, 0, 0, 0, 116,
117, 248, 249, 250, 251, 252, 253, 118, 119, 254, 255, 256, 257, 258,
259, 120, 121, 0, 0, 0, 0, 0, 0, 122, 123, 0, 0, 0, 0, 0, 0, 124, 125, 0,
0, 0, 0, 0, 0, 126, 127, 0, 0, 0, 0, 0, 0, 128, 129, 0, 0, 0, 0, 0, 0, 0,
130, 0, 0, 0, 0, 0, 0, 131, 132, 260, 261, 262, 263, 264, 265, 133, 134,
266, 267, 268, 269, 270, 271, 272, 0, 0, 0, 273, 0, 0, 0, 0, 0, 0, 0,
274, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, 0,
0, 0, 0, 276, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 277, 0, 0, 0, 0, 0, 0, 0, 136, 0
},
{ /* page 33, index 13 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
278, 0, 279, 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 281, 0, 282, 0,
283, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 34, index 14 */
0, 0, 0, 284, 0, 0, 0, 0, 285, 0, 0, 286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 287, 0, 288, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 289, 0, 0, 0, 0, 0, 0, 290,
0, 291, 0, 0, 292, 0, 0, 0, 0, 293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 294, 0, 0, 295, 296, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 297, 298, 0, 0, 299, 300, 0, 0, 301, 302, 303, 304, 0, 0, 0, 0,
305, 306, 0, 0, 307, 308, 0, 0, 0, 0, 0, 0, 0, 0, 0, 309, 310, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 311, 0, 0, 0, 0, 0, 312, 313, 0, 314,
0, 0, 0, 0, 0, 0, 315, 316, 317, 318, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{ /* page 48, index 15 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 319, 0,
0, 0, 0, 320, 0, 321, 0, 322, 0, 323, 0, 324, 0, 325, 0, 326, 0, 327, 0,
328, 0, 329, 0, 330, 0, 331, 0, 0, 332, 0, 333, 0, 334, 0, 0, 0, 0, 0, 0,
137, 0, 0, 138, 0, 0, 139, 0, 0, 140, 0, 0, 141, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 386, 387,
0, 0, 335, 0, 0, 0, 0, 0, 0, 0, 0, 336, 0, 0, 0, 0, 337, 0, 338, 0, 339,
0, 340, 0, 341, 0, 342, 0, 343, 0, 344, 0, 345, 0, 346, 0, 347, 0, 348,
0, 0, 349, 0, 350, 0, 351, 0, 0, 0, 0, 0, 0, 142, 0, 0, 143, 0, 0, 144,
0, 0, 145, 0, 0, 146, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 352, 353, 354, 355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 356, 0, 0
}
};
static const gint16 compose_table[COMPOSE_TABLE_LAST + 1] = {
0 /* page 0 */,
1 /* page 1 */,
2 /* page 2 */,
3 /* page 3 */,
4 /* page 4 */,
0 + G_UNICODE_MAX_TABLE_INDEX,
5 /* page 6 */,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
6 /* page 9 */,
0 + G_UNICODE_MAX_TABLE_INDEX,
7 /* page 11 */,
8 /* page 12 */,
9 /* page 13 */,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
10 /* page 16 */,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
11 /* page 30 */,
12 /* page 31 */,
0 + G_UNICODE_MAX_TABLE_INDEX,
13 /* page 33 */,
14 /* page 34 */,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
0 + G_UNICODE_MAX_TABLE_INDEX,
15 /* page 48 */
};
static const guint16 compose_first_single[][2] = {
{ 0x0338, 0x226e },
{ 0x0338, 0x2260 },
{ 0x0338, 0x226f },
{ 0x0307, 0x1e1e },
{ 0x0302, 0x0134 },
{ 0x0307, 0x1e1f },
{ 0x0304, 0x01de },
{ 0x0301, 0x01fa },
{ 0x0301, 0x1e08 },
{ 0x0301, 0x1e2e },
{ 0x0304, 0x022a },
{ 0x0301, 0x01fe },
{ 0x0304, 0x01df },
{ 0x0301, 0x01fb },
{ 0x0301, 0x1e09 },
{ 0x0301, 0x1e2f },
{ 0x0304, 0x022b },
{ 0x0301, 0x01ff },
{ 0x0307, 0x1e64 },
{ 0x0307, 0x1e65 },
{ 0x0307, 0x1e66 },
{ 0x0307, 0x1e67 },
{ 0x0301, 0x1e78 },
{ 0x0301, 0x1e79 },
{ 0x0308, 0x1e7a },
{ 0x0308, 0x1e7b },
{ 0x0307, 0x1e9b },
{ 0x030c, 0x01ee },
{ 0x0304, 0x01ec },
{ 0x0304, 0x01ed },
{ 0x0304, 0x01e0 },
{ 0x0304, 0x01e1 },
{ 0x0306, 0x1e1c },
{ 0x0306, 0x1e1d },
{ 0x0304, 0x0230 },
{ 0x0304, 0x0231 },
{ 0x030c, 0x01ef },
{ 0x0314, 0x1fec },
{ 0x0345, 0x1fb4 },
{ 0x0345, 0x1fc4 },
{ 0x0345, 0x1ff4 },
{ 0x0308, 0x0407 },
{ 0x0301, 0x0403 },
{ 0x0308, 0x04de },
{ 0x0301, 0x040c },
{ 0x0308, 0x04e6 },
{ 0x0308, 0x04f4 },
{ 0x0308, 0x04f8 },
{ 0x0308, 0x04ec },
{ 0x0301, 0x0453 },
{ 0x0308, 0x04df },
{ 0x0301, 0x045c },
{ 0x0308, 0x04e7 },
{ 0x0308, 0x04f5 },
{ 0x0308, 0x04f9 },
{ 0x0308, 0x04ed },
{ 0x0308, 0x0457 },
{ 0x030f, 0x0476 },
{ 0x030f, 0x0477 },
{ 0x0308, 0x04da },
{ 0x0308, 0x04db },
{ 0x0308, 0x04ea },
{ 0x0308, 0x04eb },
{ 0x0654, 0x0624 },
{ 0x0654, 0x0626 },
{ 0x0654, 0x06c2 },
{ 0x0654, 0x06d3 },
{ 0x0654, 0x06c0 },
{ 0x093c, 0x0929 },
{ 0x093c, 0x0931 },
{ 0x093c, 0x0934 },
{ 0x0bd7, 0x0b94 },
{ 0x0bbe, 0x0bcb },
{ 0x0c56, 0x0c48 },
{ 0x0cd5, 0x0cc0 },
{ 0x0cd5, 0x0ccb },
{ 0x0d3e, 0x0d4b },
{ 0x0dca, 0x0ddd },
{ 0x102e, 0x1026 },
{ 0x0304, 0x1e38 },
{ 0x0304, 0x1e39 },
{ 0x0304, 0x1e5c },
{ 0x0304, 0x1e5d },
{ 0x0307, 0x1e68 },
{ 0x0307, 0x1e69 },
{ 0x0302, 0x1ec6 },
{ 0x0302, 0x1ec7 },
{ 0x0302, 0x1ed8 },
{ 0x0302, 0x1ed9 },
{ 0x0345, 0x1f82 },
{ 0x0345, 0x1f83 },
{ 0x0345, 0x1f84 },
{ 0x0345, 0x1f85 },
{ 0x0345, 0x1f86 },
{ 0x0345, 0x1f87 },
{ 0x0345, 0x1f8a },
{ 0x0345, 0x1f8b },
{ 0x0345, 0x1f8c },
{ 0x0345, 0x1f8d },
{ 0x0345, 0x1f8e },
{ 0x0345, 0x1f8f },
{ 0x0345, 0x1f92 },
{ 0x0345, 0x1f93 },
{ 0x0345, 0x1f94 },
{ 0x0345, 0x1f95 },
{ 0x0345, 0x1f96 },
{ 0x0345, 0x1f97 },
{ 0x0345, 0x1f9a },
{ 0x0345, 0x1f9b },
{ 0x0345, 0x1f9c },
{ 0x0345, 0x1f9d },
{ 0x0345, 0x1f9e },
{ 0x0345, 0x1f9f },
{ 0x0345, 0x1fa2 },
{ 0x0345, 0x1fa3 },
{ 0x0345, 0x1fa4 },
{ 0x0345, 0x1fa5 },
{ 0x0345, 0x1fa6 },
{ 0x0345, 0x1fa7 },
{ 0x0345, 0x1faa },
{ 0x0345, 0x1fab },
{ 0x0345, 0x1fac },
{ 0x0345, 0x1fad },
{ 0x0345, 0x1fae },
{ 0x0345, 0x1faf },
{ 0x0345, 0x1fb2 },
{ 0x0345, 0x1fc2 },
{ 0x0345, 0x1ff2 },
{ 0x0345, 0x1fb7 },
{ 0x0345, 0x1fc7 },
{ 0x0345, 0x1ff7 },
{ 0x0338, 0x219a },
{ 0x0338, 0x219b },
{ 0x0338, 0x21ae },
{ 0x0338, 0x21cd },
{ 0x0338, 0x21cf },
{ 0x0338, 0x21ce },
{ 0x0338, 0x2204 },
{ 0x0338, 0x2209 },
{ 0x0338, 0x220c },
{ 0x0338, 0x2224 },
{ 0x0338, 0x2226 },
{ 0x0338, 0x2241 },
{ 0x0338, 0x2244 },
{ 0x0338, 0x2247 },
{ 0x0338, 0x2249 },
{ 0x0338, 0x226d },
{ 0x0338, 0x2262 },
{ 0x0338, 0x2270 },
{ 0x0338, 0x2271 },
{ 0x0338, 0x2274 },
{ 0x0338, 0x2275 },
{ 0x0338, 0x2278 },
{ 0x0338, 0x2279 },
{ 0x0338, 0x2280 },
{ 0x0338, 0x2281 },
{ 0x0338, 0x22e0 },
{ 0x0338, 0x22e1 },
{ 0x0338, 0x2284 },
{ 0x0338, 0x2285 },
{ 0x0338, 0x2288 },
{ 0x0338, 0x2289 },
{ 0x0338, 0x22e2 },
{ 0x0338, 0x22e3 },
{ 0x0338, 0x22ac },
{ 0x0338, 0x22ad },
{ 0x0338, 0x22ae },
{ 0x0338, 0x22af },
{ 0x0338, 0x22ea },
{ 0x0338, 0x22eb },
{ 0x0338, 0x22ec },
{ 0x0338, 0x22ed },
{ 0x3099, 0x3094 },
{ 0x3099, 0x304c },
{ 0x3099, 0x304e },
{ 0x3099, 0x3050 },
{ 0x3099, 0x3052 },
{ 0x3099, 0x3054 },
{ 0x3099, 0x3056 },
{ 0x3099, 0x3058 },
{ 0x3099, 0x305a },
{ 0x3099, 0x305c },
{ 0x3099, 0x305e },
{ 0x3099, 0x3060 },
{ 0x3099, 0x3062 },
{ 0x3099, 0x3065 },
{ 0x3099, 0x3067 },
{ 0x3099, 0x3069 },
{ 0x3099, 0x309e },
{ 0x3099, 0x30f4 },
{ 0x3099, 0x30ac },
{ 0x3099, 0x30ae },
{ 0x3099, 0x30b0 },
{ 0x3099, 0x30b2 },
{ 0x3099, 0x30b4 },
{ 0x3099, 0x30b6 },
{ 0x3099, 0x30b8 },
{ 0x3099, 0x30ba },
{ 0x3099, 0x30bc },
{ 0x3099, 0x30be },
{ 0x3099, 0x30c0 },
{ 0x3099, 0x30c2 },
{ 0x3099, 0x30c5 },
{ 0x3099, 0x30c7 },
{ 0x3099, 0x30c9 },
{ 0x3099, 0x30f7 },
{ 0x3099, 0x30f8 },
{ 0x3099, 0x30f9 },
{ 0x3099, 0x30fa },
{ 0x3099, 0x30fe }
};
static const guint16 compose_second_single[][2] = {
{ 0x0627, 0x0622 },
{ 0x0627, 0x0623 },
{ 0x0627, 0x0625 },
{ 0x09c7, 0x09cb },
{ 0x09c7, 0x09cc },
{ 0x0b47, 0x0b4b },
{ 0x0b47, 0x0b48 },
{ 0x0b47, 0x0b4c },
{ 0x0bc6, 0x0bca },
{ 0x0bc6, 0x0bcc },
{ 0x0cc6, 0x0cca },
{ 0x0cc6, 0x0cc7 },
{ 0x0cc6, 0x0cc8 },
{ 0x0d46, 0x0d4a },
{ 0x0d46, 0x0d4c },
{ 0x0dd9, 0x0dda },
{ 0x0dd9, 0x0ddc },
{ 0x0dd9, 0x0dde }
};
static const guint16 compose_array[146][31] = {
{ 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x0100, 0x0102, 0x0226, 0x00c4, 0x1ea2, 0x00c5, 0, 0x01cd, 0x0200, 0x0202, 0, 0, 0, 0x1ea0, 0, 0x1e00, 0, 0, 0x0104, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e04, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e06, 0, 0, 0, 0 },
{ 0, 0x0106, 0x0108, 0, 0, 0, 0x010a, 0, 0, 0, 0, 0x010c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00c7, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e0a, 0, 0, 0, 0, 0x010e, 0, 0, 0, 0, 0, 0x1e0c, 0, 0, 0, 0x1e10, 0, 0x1e12, 0, 0, 0x1e0e, 0, 0, 0, 0 },
{ 0x00c8, 0x00c9, 0x00ca, 0x1ebc, 0x0112, 0x0114, 0x0116, 0x00cb, 0x1eba, 0, 0, 0x011a, 0x0204, 0x0206, 0, 0, 0, 0x1eb8, 0, 0, 0, 0x0228, 0x0118, 0x1e18, 0, 0x1e1a, 0, 0, 0, 0, 0 },
{ 0, 0x01f4, 0x011c, 0, 0x1e20, 0x011e, 0x0120, 0, 0, 0, 0, 0x01e6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0122, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0x0124, 0, 0, 0, 0x1e22, 0x1e26, 0, 0, 0, 0x021e, 0, 0, 0, 0, 0, 0x1e24, 0, 0, 0, 0x1e28, 0, 0, 0x1e2a, 0, 0, 0, 0, 0, 0 },
{ 0x00cc, 0x00cd, 0x00ce, 0x0128, 0x012a, 0x012c, 0x0130, 0x00cf, 0x1ec8, 0, 0, 0x01cf, 0x0208, 0x020a, 0, 0, 0, 0x1eca, 0, 0, 0, 0, 0x012e, 0, 0, 0x1e2c, 0, 0, 0, 0, 0 },
{ 0, 0x1e30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01e8, 0, 0, 0, 0, 0, 0x1e32, 0, 0, 0, 0x0136, 0, 0, 0, 0, 0x1e34, 0, 0, 0, 0 },
{ 0, 0x0139, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x013d, 0, 0, 0, 0, 0, 0x1e36, 0, 0, 0, 0x013b, 0, 0x1e3c, 0, 0, 0x1e3a, 0, 0, 0, 0 },
{ 0, 0x1e3e, 0, 0, 0, 0, 0x1e40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x01f8, 0x0143, 0, 0x00d1, 0, 0, 0x1e44, 0, 0, 0, 0, 0x0147, 0, 0, 0, 0, 0, 0x1e46, 0, 0, 0, 0x0145, 0, 0x1e4a, 0, 0, 0x1e48, 0, 0, 0, 0 },
{ 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x014c, 0x014e, 0x022e, 0x00d6, 0x1ece, 0, 0x0150, 0x01d1, 0x020c, 0x020e, 0, 0, 0x01a0, 0x1ecc, 0, 0, 0, 0, 0x01ea, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x1e54, 0, 0, 0, 0, 0x1e56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x0154, 0, 0, 0, 0, 0x1e58, 0, 0, 0, 0, 0x0158, 0x0210, 0x0212, 0, 0, 0, 0x1e5a, 0, 0, 0, 0x0156, 0, 0, 0, 0, 0x1e5e, 0, 0, 0, 0 },
{ 0, 0x015a, 0x015c, 0, 0, 0, 0x1e60, 0, 0, 0, 0, 0x0160, 0, 0, 0, 0, 0, 0x1e62, 0, 0, 0x0218, 0x015e, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e6a, 0, 0, 0, 0, 0x0164, 0, 0, 0, 0, 0, 0x1e6c, 0, 0, 0x021a, 0x0162, 0, 0x1e70, 0, 0, 0x1e6e, 0, 0, 0, 0 },
{ 0x00d9, 0x00da, 0x00db, 0x0168, 0x016a, 0x016c, 0, 0x00dc, 0x1ee6, 0x016e, 0x0170, 0x01d3, 0x0214, 0x0216, 0, 0, 0x01af, 0x1ee4, 0x1e72, 0, 0, 0, 0x0172, 0x1e76, 0, 0x1e74, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0x1e7c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e7e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1e80, 0x1e82, 0x0174, 0, 0, 0, 0x1e86, 0x1e84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e8a, 0x1e8c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ef2, 0x00dd, 0x0176, 0x1ef8, 0x0232, 0, 0x1e8e, 0x0178, 0x1ef6, 0, 0, 0, 0, 0, 0, 0, 0, 0x1ef4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x0179, 0x1e90, 0, 0, 0, 0x017b, 0, 0, 0, 0, 0x017d, 0, 0, 0, 0, 0, 0x1e92, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e94, 0, 0, 0, 0 },
{ 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x0101, 0x0103, 0x0227, 0x00e4, 0x1ea3, 0x00e5, 0, 0x01ce, 0x0201, 0x0203, 0, 0, 0, 0x1ea1, 0, 0x1e01, 0, 0, 0x0105, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e03, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e05, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e07, 0, 0, 0, 0 },
{ 0, 0x0107, 0x0109, 0, 0, 0, 0x010b, 0, 0, 0, 0, 0x010d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x00e7, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e0b, 0, 0, 0, 0, 0x010f, 0, 0, 0, 0, 0, 0x1e0d, 0, 0, 0, 0x1e11, 0, 0x1e13, 0, 0, 0x1e0f, 0, 0, 0, 0 },
{ 0x00e8, 0x00e9, 0x00ea, 0x1ebd, 0x0113, 0x0115, 0x0117, 0x00eb, 0x1ebb, 0, 0, 0x011b, 0x0205, 0x0207, 0, 0, 0, 0x1eb9, 0, 0, 0, 0x0229, 0x0119, 0x1e19, 0, 0x1e1b, 0, 0, 0, 0, 0 },
{ 0, 0x01f5, 0x011d, 0, 0x1e21, 0x011f, 0x0121, 0, 0, 0, 0, 0x01e7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0123, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0x0125, 0, 0, 0, 0x1e23, 0x1e27, 0, 0, 0, 0x021f, 0, 0, 0, 0, 0, 0x1e25, 0, 0, 0, 0x1e29, 0, 0, 0x1e2b, 0, 0x1e96, 0, 0, 0, 0 },
{ 0x00ec, 0x00ed, 0x00ee, 0x0129, 0x012b, 0x012d, 0, 0x00ef, 0x1ec9, 0, 0, 0x01d0, 0x0209, 0x020b, 0, 0, 0, 0x1ecb, 0, 0, 0, 0, 0x012f, 0, 0, 0x1e2d, 0, 0, 0, 0, 0 },
{ 0, 0, 0x0135, 0, 0, 0, 0, 0, 0, 0, 0, 0x01f0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x1e31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01e9, 0, 0, 0, 0, 0, 0x1e33, 0, 0, 0, 0x0137, 0, 0, 0, 0, 0x1e35, 0, 0, 0, 0 },
{ 0, 0x013a, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x013e, 0, 0, 0, 0, 0, 0x1e37, 0, 0, 0, 0x013c, 0, 0x1e3d, 0, 0, 0x1e3b, 0, 0, 0, 0 },
{ 0, 0x1e3f, 0, 0, 0, 0, 0x1e41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x01f9, 0x0144, 0, 0x00f1, 0, 0, 0x1e45, 0, 0, 0, 0, 0x0148, 0, 0, 0, 0, 0, 0x1e47, 0, 0, 0, 0x0146, 0, 0x1e4b, 0, 0, 0x1e49, 0, 0, 0, 0 },
{ 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x014d, 0x014f, 0x022f, 0x00f6, 0x1ecf, 0, 0x0151, 0x01d2, 0x020d, 0x020f, 0, 0, 0x01a1, 0x1ecd, 0, 0, 0, 0, 0x01eb, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x1e55, 0, 0, 0, 0, 0x1e57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x0155, 0, 0, 0, 0, 0x1e59, 0, 0, 0, 0, 0x0159, 0x0211, 0x0213, 0, 0, 0, 0x1e5b, 0, 0, 0, 0x0157, 0, 0, 0, 0, 0x1e5f, 0, 0, 0, 0 },
{ 0, 0x015b, 0x015d, 0, 0, 0, 0x1e61, 0, 0, 0, 0, 0x0161, 0, 0, 0, 0, 0, 0x1e63, 0, 0, 0x0219, 0x015f, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e6b, 0x1e97, 0, 0, 0, 0x0165, 0, 0, 0, 0, 0, 0x1e6d, 0, 0, 0x021b, 0x0163, 0, 0x1e71, 0, 0, 0x1e6f, 0, 0, 0, 0 },
{ 0x00f9, 0x00fa, 0x00fb, 0x0169, 0x016b, 0x016d, 0, 0x00fc, 0x1ee7, 0x016f, 0x0171, 0x01d4, 0x0215, 0x0217, 0, 0, 0x01b0, 0x1ee5, 0x1e73, 0, 0, 0, 0x0173, 0x1e77, 0, 0x1e75, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0x1e7d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e7f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1e81, 0x1e83, 0x0175, 0, 0, 0, 0x1e87, 0x1e85, 0, 0x1e98, 0, 0, 0, 0, 0, 0, 0, 0x1e89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0x1e8b, 0x1e8d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ef3, 0x00fd, 0x0177, 0x1ef9, 0x0233, 0, 0x1e8f, 0x00ff, 0x1ef7, 0x1e99, 0, 0, 0, 0, 0, 0, 0, 0x1ef5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x017a, 0x1e91, 0, 0, 0, 0x017c, 0, 0, 0, 0, 0x017e, 0, 0, 0, 0, 0, 0x1e93, 0, 0, 0, 0, 0, 0, 0, 0, 0x1e95, 0, 0, 0, 0 },
{ 0x1fed, 0x0385, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fc1, 0, 0, 0 },
{ 0x1ea6, 0x1ea4, 0, 0x1eaa, 0, 0, 0, 0, 0x1ea8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x01fc, 0, 0, 0x01e2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ec0, 0x1ebe, 0, 0x1ec4, 0, 0, 0, 0, 0x1ec2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ed2, 0x1ed0, 0, 0x1ed6, 0, 0, 0, 0, 0x1ed4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x1e4c, 0, 0, 0x022c, 0, 0, 0x1e4e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x01db, 0x01d7, 0, 0, 0x01d5, 0, 0, 0, 0, 0, 0, 0x01d9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ea7, 0x1ea5, 0, 0x1eab, 0, 0, 0, 0, 0x1ea9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x01fd, 0, 0, 0x01e3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ec1, 0x1ebf, 0, 0x1ec5, 0, 0, 0, 0, 0x1ec3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ed3, 0x1ed1, 0, 0x1ed7, 0, 0, 0, 0, 0x1ed5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0x1e4d, 0, 0, 0x022d, 0, 0, 0x1e4f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x01dc, 0x01d8, 0, 0, 0x01d6, 0, 0, 0, 0, 0, 0, 0x01da, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1eb0, 0x1eae, 0, 0x1eb4, 0, 0, 0, 0, 0x1eb2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1eb1, 0x1eaf, 0, 0x1eb5, 0, 0, 0, 0, 0x1eb3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1e14, 0x1e16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1e15, 0x1e17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1e50, 0x1e52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1e51, 0x1e53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1edc, 0x1eda, 0, 0x1ee0, 0, 0, 0, 0, 0x1ede, 0, 0, 0, 0, 0, 0, 0, 0, 0x1ee2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1edd, 0x1edb, 0, 0x1ee1, 0, 0, 0, 0, 0x1edf, 0, 0, 0, 0, 0, 0, 0, 0, 0x1ee3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1eea, 0x1ee8, 0, 0x1eee, 0, 0, 0, 0, 0x1eec, 0, 0, 0, 0, 0, 0, 0, 0, 0x1ef0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1eeb, 0x1ee9, 0, 0x1eef, 0, 0, 0, 0, 0x1eed, 0, 0, 0, 0, 0, 0, 0, 0, 0x1ef1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1fba, 0x0386, 0, 0, 0x1fb9, 0x1fb8, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f08, 0x1f09, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fbc, 0, 0 },
{ 0x1fc8, 0x0388, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f18, 0x1f19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1fca, 0x0389, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f28, 0x1f29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fcc, 0, 0 },
{ 0x1fda, 0x038a, 0, 0, 0x1fd9, 0x1fd8, 0, 0x03aa, 0, 0, 0, 0, 0, 0, 0x1f38, 0x1f39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ff8, 0x038c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f48, 0x1f49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1fea, 0x038e, 0, 0, 0x1fe9, 0x1fe8, 0, 0x03ab, 0, 0, 0, 0, 0, 0, 0, 0x1f59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1ffa, 0x038f, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f68, 0x1f69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1ffc, 0, 0 },
{ 0x1f70, 0x03ac, 0, 0, 0x1fb1, 0x1fb0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f00, 0x1f01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fb6, 0x1fb3, 0, 0 },
{ 0x1f72, 0x03ad, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f10, 0x1f11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f74, 0x03ae, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f20, 0x1f21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fc6, 0x1fc3, 0, 0 },
{ 0x1f76, 0x03af, 0, 0, 0x1fd1, 0x1fd0, 0, 0x03ca, 0, 0, 0, 0, 0, 0, 0x1f30, 0x1f31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fd6, 0, 0, 0 },
{ 0x1f78, 0x03cc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f40, 0x1f41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fe4, 0x1fe5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f7a, 0x03cd, 0, 0, 0x1fe1, 0x1fe0, 0, 0x03cb, 0, 0, 0, 0, 0, 0, 0x1f50, 0x1f51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fe6, 0, 0, 0 },
{ 0x1f7c, 0x03ce, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f60, 0x1f61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1ff6, 0x1ff3, 0, 0 },
{ 0x1fd2, 0x0390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fd7, 0, 0, 0 },
{ 0x1fe2, 0x03b0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fe7, 0, 0, 0 },
{ 0, 0x03d3, 0, 0, 0, 0, 0, 0x03d4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0x04d0, 0, 0x04d2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x0400, 0, 0, 0, 0, 0x04d6, 0, 0x0401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0x04c1, 0, 0x04dc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x040d, 0, 0, 0, 0x04e2, 0x0419, 0, 0x04e4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0x04ee, 0x040e, 0, 0x04f0, 0, 0, 0x04f2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0x04d1, 0, 0x04d3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x0450, 0, 0, 0, 0, 0x04d7, 0, 0x0451, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0x04c2, 0, 0x04dd, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x045d, 0, 0, 0, 0x04e3, 0x0439, 0, 0x04e5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0x04ef, 0x045e, 0, 0x04f1, 0, 0, 0x04f3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0x1eac, 0, 0, 0x1eb6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0x1ead, 0, 0, 0x1eb7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f02, 0x1f04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f06, 0x1f80, 0, 0 },
{ 0x1f03, 0x1f05, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f07, 0x1f81, 0, 0 },
{ 0x1f0a, 0x1f0c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f0e, 0x1f88, 0, 0 },
{ 0x1f0b, 0x1f0d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f0f, 0x1f89, 0, 0 },
{ 0x1f12, 0x1f14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f13, 0x1f15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f1a, 0x1f1c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f1b, 0x1f1d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f22, 0x1f24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f26, 0x1f90, 0, 0 },
{ 0x1f23, 0x1f25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f27, 0x1f91, 0, 0 },
{ 0x1f2a, 0x1f2c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f2e, 0x1f98, 0, 0 },
{ 0x1f2b, 0x1f2d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f2f, 0x1f99, 0, 0 },
{ 0x1f32, 0x1f34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f36, 0, 0, 0 },
{ 0x1f33, 0x1f35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f37, 0, 0, 0 },
{ 0x1f3a, 0x1f3c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f3e, 0, 0, 0 },
{ 0x1f3b, 0x1f3d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f3f, 0, 0, 0 },
{ 0x1f42, 0x1f44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f43, 0x1f45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f4a, 0x1f4c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f4b, 0x1f4d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0x1f52, 0x1f54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f56, 0, 0, 0 },
{ 0x1f53, 0x1f55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f57, 0, 0, 0 },
{ 0x1f5b, 0x1f5d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f5f, 0, 0, 0 },
{ 0x1f62, 0x1f64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f66, 0x1fa0, 0, 0 },
{ 0x1f63, 0x1f65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f67, 0x1fa1, 0, 0 },
{ 0x1f6a, 0x1f6c, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f6e, 0x1fa8, 0, 0 },
{ 0x1f6b, 0x1f6d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1f6f, 0x1fa9, 0, 0 },
{ 0x1fcd, 0x1fce, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fcf, 0, 0, 0 },
{ 0x1fdd, 0x1fde, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1fdf, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3070, 0x3071 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3073, 0x3074 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3076, 0x3077 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3079, 0x307a },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x307c, 0x307d },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x30d0, 0x30d1 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x30d3, 0x30d4 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x30d6, 0x30d7 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x30d9, 0x30da },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x30dc, 0x30dd }
};

File diff suppressed because it is too large Load Diff

View File

@ -1,171 +0,0 @@
/* Recode strings between character sets, using iconv.
Copyright (C) 2002-2018 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1, or (at
your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
/* Get prototype. */
#include "iconvme.h"
/* Get malloc. */
#include <stdlib.h>
/* Get strcmp. */
#include <string.h>
/* Get errno. */
#include <errno.h>
#ifdef _LIBC
# define HAVE_ICONV 1
#else
/* Get strdup. */
# include "strdup.h"
#endif
#if HAVE_ICONV
/* Get iconv etc. */
# include <iconv.h>
/* Get MB_LEN_MAX, CHAR_BIT. */
# include <limits.h>
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
/* Convert a zero-terminated string STR from the FROM_CODSET code set
to the TO_CODESET code set. The returned string is allocated using
malloc, and must be dellocated by the caller using free. On
failure, NULL is returned and errno holds the error reason. Note
that if TO_CODESET uses \0 for anything but to terminate the
string, the caller of this function may have difficulties finding
out the length of the output string. */
char *
iconv_string (const char *str, const char *from_codeset,
const char *to_codeset)
{
char *dest = NULL;
#if HAVE_ICONV
iconv_t cd;
char *outp;
char *p = (char *) str;
size_t inbytes_remaining = strlen (p);
/* Guess the maximum length the output string can have. */
size_t outbuf_size = inbytes_remaining + 1;
size_t outbytes_remaining;
size_t err;
int have_error = 0;
/* Use a worst-case output size guess, so long as that wouldn't be
too large for comfort. It's OK if the guess is wrong so long as
it's nonzero. */
size_t approx_sqrt_SIZE_MAX = SIZE_MAX >> (sizeof (size_t) * CHAR_BIT / 2);
if (outbuf_size <= approx_sqrt_SIZE_MAX / MB_LEN_MAX)
outbuf_size *= MB_LEN_MAX;
outbytes_remaining = outbuf_size - 1;
#endif
if (strcmp (to_codeset, from_codeset) == 0)
return strdup (str);
#if HAVE_ICONV
cd = iconv_open (to_codeset, from_codeset);
if (cd == (iconv_t) -1)
return NULL;
outp = dest = (char *) malloc (outbuf_size);
if (dest == NULL)
goto out;
again:
err = iconv (cd, &p, &inbytes_remaining, &outp, &outbytes_remaining);
if (err == (size_t) - 1)
{
switch (errno)
{
case EINVAL:
/* Incomplete text, do not report an error */
break;
case E2BIG:
{
size_t used = outp - dest;
size_t newsize = outbuf_size * 2;
char *newdest;
if (newsize <= outbuf_size)
{
errno = ENOMEM;
have_error = 1;
goto out;
}
newdest = (char *) realloc (dest, newsize);
if (newdest == NULL)
{
have_error = 1;
goto out;
}
dest = newdest;
outbuf_size = newsize;
outp = dest + used;
outbytes_remaining = outbuf_size - used - 1; /* -1 for NUL */
goto again;
}
break;
case EILSEQ:
have_error = 1;
break;
default:
have_error = 1;
break;
}
}
*outp = '\0';
out:
{
int save_errno = errno;
if (iconv_close (cd) < 0 && !have_error)
{
/* If we didn't have a real error before, make sure we restore
the iconv_close error below. */
save_errno = errno;
have_error = 1;
}
if (have_error && dest)
{
free (dest);
dest = NULL;
errno = save_errno;
}
}
#else
errno = ENOSYS;
#endif
return dest;
}

View File

@ -1,25 +0,0 @@
/* Recode strings between character sets, using iconv.
Copyright (C) 2004-2018 Free Software Foundation, Inc.
Written by Simon Josefsson.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, see
<http://www.gnu.org/licenses/>. */
#ifndef ICONVME_H
# define ICONVME_H
extern char *iconv_string (const char *string, const char *from_code,
const char *to_code);
#endif /* ICONVME_H */

View File

@ -1,142 +0,0 @@
/* idn-stub.c --- Stub to dlopen libcidn.so and invoke idna_to_ascii_lz.
* Copyright (C) 2003, 2004 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <gnu/lib-names.h>
#include <libc-lock.h>
/* Get specification for idna_to_ascii_lz. */
#include "idna.h"
/* Handle of the libidn DSO. */
static void *h;
static int (*to_ascii_lz) (const char *input, char **output, int flags);
static int (*to_unicode_lzlz) (const char *input, char **output, int flags);
static void
load_dso (void)
{
/* Lock protecting the DSO loading. */
__libc_lock_define_initialized (static, lock);
__libc_lock_lock (lock);
/* Retest in case some other thread arrived here at the same time. */
if (h == NULL)
{
h = __libc_dlopen (LIBCIDN_SO);
if (h == NULL)
h = (void *) 1l;
else
{
/* Get the function we are interested in. */
to_ascii_lz = __libc_dlsym (h, "idna_to_ascii_lz");
to_unicode_lzlz = __libc_dlsym (h, "idna_to_unicode_lzlz");
if (to_ascii_lz == NULL || to_unicode_lzlz == NULL)
{
__libc_dlclose (h);
h = (void *) 1l;
}
}
}
__libc_lock_unlock (lock);
}
/* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
return IDNA_DLOPEN_ERROR on failure. */
int
__idna_to_unicode_lzlz (const char *input, char **output, int flags)
{
/* If the input string contains no "xn--" prefix for a component of
the name we can pass it up right away. */
const char *cp = input;
while (*cp != '\0')
{
if (strncmp (cp, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX)) == 0)
break;
/* On to the next part of the name. */
cp = __strchrnul (cp, '.');
if (*cp == '.')
++cp;
}
if (*cp == '\0')
{
*output = (char *) input;
return IDNA_SUCCESS;
}
if (h == NULL)
load_dso ();
if (h == (void *) 1l)
return IDNA_DLOPEN_ERROR;
return to_unicode_lzlz (input, output, flags);
}
/* Stub to dlopen libcidn.so and invoke the real idna_to_ascii_lz, or
return IDNA_DLOPEN_ERROR on failure. */
int
__idna_to_ascii_lz (const char *input, char **output, int flags)
{
/* If the input string contains no non-ASCII character the output
string will be the same. No valid locale encoding does not have
this property. */
const char *cp = input;
while (*cp != '\0' && isascii (*cp))
++cp;
if (*cp == '\0')
{
*output = (char *) input;
return IDNA_SUCCESS;
}
if (h == NULL)
load_dso ();
if (h == (void *) 1l)
return IDNA_DLOPEN_ERROR;
return to_ascii_lz (input, output, flags);
}
#if IS_IN (libc)
libc_freeres_fn (unload_libidn)
{
if (h != NULL && h != (void *) 1l)
{
__libc_dlclose (h);
h = (void *) 1l;
}
}
#endif

View File

@ -1,834 +0,0 @@
/* idna.c Convert to or from IDN strings.
* Copyright (C) 2002, 2003, 2004, 2011 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stringprep.h>
#include <punycode.h>
#include <stdint.h>
#include "idna.h"
#define DOTP(c) ((c) == 0x002E || (c) == 0x3002 || \
(c) == 0xFF0E || (c) == 0xFF61)
/* Core functions */
/**
* idna_to_ascii_4i
* @in: input array with unicode code points.
* @inlen: length of input array with unicode code points.
* @out: output zero terminated string that must have room for at
* least 63 characters plus the terminating zero.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* The ToASCII operation takes a sequence of Unicode code points that make
* up one label and transforms it into a sequence of code points in the
* ASCII range (0..7F). If ToASCII succeeds, the original sequence and the
* resulting sequence are equivalent labels.
*
* It is important to note that the ToASCII operation can fail. ToASCII
* fails if any step of it fails. If any step of the ToASCII operation
* fails on any label in a domain name, that domain name MUST NOT be used
* as an internationalized domain name. The method for deadling with this
* failure is application-specific.
*
* The inputs to ToASCII are a sequence of code points, the AllowUnassigned
* flag, and the UseSTD3ASCIIRules flag. The output of ToASCII is either a
* sequence of ASCII code points or a failure condition.
*
* ToASCII never alters a sequence of code points that are all in the ASCII
* range to begin with (although it could fail). Applying the ToASCII
* operation multiple times has exactly the same effect as applying it just
* once.
*
* Return value: Returns 0 on success, or an error code.
*/
int
idna_to_ascii_4i (const uint32_t * in, size_t inlen, char *out, int flags)
{
size_t len, outlen;
uint32_t *src; /* XXX don't need to copy data? */
int rc;
/*
* ToASCII consists of the following steps:
*
* 1. If all code points in the sequence are in the ASCII range (0..7F)
* then skip to step 3.
*/
{
size_t i;
int inasciirange;
inasciirange = 1;
for (i = 0; i < inlen; i++)
if (in[i] > 0x7F)
inasciirange = 0;
if (inasciirange)
{
src = malloc (sizeof (in[0]) * (inlen + 1));
if (src == NULL)
return IDNA_MALLOC_ERROR;
memcpy (src, in, sizeof (in[0]) * inlen);
src[inlen] = 0;
goto step3;
}
}
/*
* 2. Perform the steps specified in [NAMEPREP] and fail if there is
* an error. The AllowUnassigned flag is used in [NAMEPREP].
*/
{
char *p;
p = stringprep_ucs4_to_utf8 (in, inlen, NULL, NULL);
if (p == NULL)
return IDNA_MALLOC_ERROR;
len = strlen (p);
do
{
char *newp;
len = 2 * len + 10; /* XXX better guess? */
newp = realloc (p, len);
if (newp == NULL)
{
free (p);
return IDNA_MALLOC_ERROR;
}
p = newp;
if (flags & IDNA_ALLOW_UNASSIGNED)
rc = stringprep_nameprep (p, len);
else
rc = stringprep_nameprep_no_unassigned (p, len);
}
while (rc == STRINGPREP_TOO_SMALL_BUFFER);
if (rc != STRINGPREP_OK)
{
free (p);
return IDNA_STRINGPREP_ERROR;
}
src = stringprep_utf8_to_ucs4 (p, -1, NULL);
free (p);
}
step3:
/*
* 3. If the UseSTD3ASCIIRules flag is set, then perform these checks:
*
* (a) Verify the absence of non-LDH ASCII code points; that is,
* the absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F.
*
* (b) Verify the absence of leading and trailing hyphen-minus;
* that is, the absence of U+002D at the beginning and end of
* the sequence.
*/
if (flags & IDNA_USE_STD3_ASCII_RULES)
{
size_t i;
for (i = 0; src[i]; i++)
if (src[i] <= 0x2C || src[i] == 0x2E || src[i] == 0x2F ||
(src[i] >= 0x3A && src[i] <= 0x40) ||
(src[i] >= 0x5B && src[i] <= 0x60) ||
(src[i] >= 0x7B && src[i] <= 0x7F))
{
free (src);
return IDNA_CONTAINS_NON_LDH;
}
if (src[0] == 0x002D || (i > 0 && src[i - 1] == 0x002D))
{
free (src);
return IDNA_CONTAINS_MINUS;
}
}
/*
* 4. If all code points in the sequence are in the ASCII range
* (0..7F), then skip to step 8.
*/
{
size_t i;
int inasciirange;
inasciirange = 1;
for (i = 0; src[i]; i++)
{
if (src[i] > 0x7F)
inasciirange = 0;
/* copy string to output buffer if we are about to skip to step8 */
if (i < 64)
out[i] = src[i];
}
if (i < 64)
out[i] = '\0';
if (inasciirange)
goto step8;
}
/*
* 5. Verify that the sequence does NOT begin with the ACE prefix.
*
*/
{
size_t i;
int match;
match = 1;
for (i = 0; match && i < strlen (IDNA_ACE_PREFIX); i++)
if (((uint32_t) IDNA_ACE_PREFIX[i] & 0xFF) != src[i])
match = 0;
if (match)
{
free (src);
return IDNA_CONTAINS_ACE_PREFIX;
}
}
/*
* 6. Encode the sequence using the encoding algorithm in [PUNYCODE]
* and fail if there is an error.
*/
for (len = 0; src[len]; len++)
;
src[len] = '\0';
outlen = 63 - strlen (IDNA_ACE_PREFIX);
rc = punycode_encode (len, src, NULL,
&outlen, &out[strlen (IDNA_ACE_PREFIX)]);
if (rc != PUNYCODE_SUCCESS)
{
free (src);
return IDNA_PUNYCODE_ERROR;
}
out[strlen (IDNA_ACE_PREFIX) + outlen] = '\0';
/*
* 7. Prepend the ACE prefix.
*/
memcpy (out, IDNA_ACE_PREFIX, strlen (IDNA_ACE_PREFIX));
/*
* 8. Verify that the number of code points is in the range 1 to 63
* inclusive (0 is excluded).
*/
step8:
free (src);
if (strlen (out) < 1 || strlen (out) > 63)
return IDNA_INVALID_LENGTH;
return IDNA_SUCCESS;
}
/* ToUnicode(). May realloc() utf8in. */
static int
idna_to_unicode_internal (char *utf8in,
uint32_t * out, size_t * outlen, int flags)
{
int rc;
char tmpout[64];
size_t utf8len = strlen (utf8in) + 1;
size_t addlen = 0;
/*
* ToUnicode consists of the following steps:
*
* 1. If the sequence contains any code points outside the ASCII range
* (0..7F) then proceed to step 2, otherwise skip to step 3.
*/
{
size_t i;
int inasciirange;
inasciirange = 1;
for (i = 0; utf8in[i]; i++)
if (utf8in[i] & ~0x7F)
inasciirange = 0;
if (inasciirange)
goto step3;
}
/*
* 2. Perform the steps specified in [NAMEPREP] and fail if there is an
* error. (If step 3 of ToASCII is also performed here, it will not
* affect the overall behavior of ToUnicode, but it is not
* necessary.) The AllowUnassigned flag is used in [NAMEPREP].
*/
do
{
char *newp = realloc (utf8in, utf8len + addlen);
if (newp == NULL)
{
free (utf8in);
return IDNA_MALLOC_ERROR;
}
utf8in = newp;
if (flags & IDNA_ALLOW_UNASSIGNED)
rc = stringprep_nameprep (utf8in, utf8len + addlen);
else
rc = stringprep_nameprep_no_unassigned (utf8in, utf8len + addlen);
addlen += 1;
}
while (rc == STRINGPREP_TOO_SMALL_BUFFER);
if (rc != STRINGPREP_OK)
{
free (utf8in);
return IDNA_STRINGPREP_ERROR;
}
/* 3. Verify that the sequence begins with the ACE prefix, and save a
* copy of the sequence.
*/
step3:
if (memcmp (IDNA_ACE_PREFIX, utf8in, strlen (IDNA_ACE_PREFIX)) != 0)
{
free (utf8in);
return IDNA_NO_ACE_PREFIX;
}
/* 4. Remove the ACE prefix.
*/
memmove (utf8in, &utf8in[strlen (IDNA_ACE_PREFIX)],
strlen (utf8in) - strlen (IDNA_ACE_PREFIX) + 1);
/* 5. Decode the sequence using the decoding algorithm in [PUNYCODE]
* and fail if there is an error. Save a copy of the result of
* this step.
*/
(*outlen)--; /* reserve one for the zero */
rc = punycode_decode (strlen (utf8in), utf8in, outlen, out, NULL);
if (rc != PUNYCODE_SUCCESS)
{
free (utf8in);
return IDNA_PUNYCODE_ERROR;
}
out[*outlen] = 0; /* add zero */
/* 6. Apply ToASCII.
*/
rc = idna_to_ascii_4i (out, *outlen, tmpout, flags);
if (rc != IDNA_SUCCESS)
{
free (utf8in);
return rc;
}
/* 7. Verify that the result of step 6 matches the saved copy from
* step 3, using a case-insensitive ASCII comparison.
*/
if (strcasecmp (utf8in, tmpout + strlen (IDNA_ACE_PREFIX)) != 0)
{
free (utf8in);
return IDNA_ROUNDTRIP_VERIFY_ERROR;
}
/* 8. Return the saved copy from step 5.
*/
free (utf8in);
return IDNA_SUCCESS;
}
/**
* idna_to_unicode_44i
* @in: input array with unicode code points.
* @inlen: length of input array with unicode code points.
* @out: output array with unicode code points.
* @outlen: on input, maximum size of output array with unicode code points,
* on exit, actual size of output array with unicode code points.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* The ToUnicode operation takes a sequence of Unicode code points
* that make up one label and returns a sequence of Unicode code
* points. If the input sequence is a label in ACE form, then the
* result is an equivalent internationalized label that is not in ACE
* form, otherwise the original sequence is returned unaltered.
*
* ToUnicode never fails. If any step fails, then the original input
* sequence is returned immediately in that step.
*
* The Punycode decoder can never output more code points than it
* inputs, but Nameprep can, and therefore ToUnicode can. Note that
* the number of octets needed to represent a sequence of code points
* depends on the particular character encoding used.
*
* The inputs to ToUnicode are a sequence of code points, the
* AllowUnassigned flag, and the UseSTD3ASCIIRules flag. The output of
* ToUnicode is always a sequence of Unicode code points.
*
* Return value: Returns error condition, but it must only be used for
* debugging purposes. The output buffer is always
* guaranteed to contain the correct data according to
* the specification (sans malloc induced errors). NB!
* This means that you normally ignore the return code
* from this function, as checking it means breaking the
* standard.
*/
int
idna_to_unicode_44i (const uint32_t * in, size_t inlen,
uint32_t * out, size_t * outlen, int flags)
{
int rc;
size_t outlensave = *outlen;
char *p;
p = stringprep_ucs4_to_utf8 (in, inlen, NULL, NULL);
if (p == NULL)
return IDNA_MALLOC_ERROR;
rc = idna_to_unicode_internal (p, out, outlen, flags);
if (rc != IDNA_SUCCESS)
{
memcpy (out, in, sizeof (in[0]) * (inlen < outlensave ?
inlen : outlensave));
*outlen = inlen;
}
/* p is freed in idna_to_unicode_internal. */
return rc;
}
/* Wrappers that handle several labels */
/**
* idna_to_ascii_4z:
* @input: zero terminated input Unicode string.
* @output: pointer to newly allocated output string.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert UCS-4 domain name to ASCII string. The domain name may
* contain several labels, separated by dots. The output buffer must
* be deallocated by the caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_ascii_4z (const uint32_t * input, char **output, int flags)
{
const uint32_t *start = input;
const uint32_t *end = input;
char buf[64];
char *out = NULL;
int rc;
/* 1) Whenever dots are used as label separators, the following
characters MUST be recognized as dots: U+002E (full stop),
U+3002 (ideographic full stop), U+FF0E (fullwidth full stop),
U+FF61 (halfwidth ideographic full stop). */
if (input[0] == 0)
{
/* Handle implicit zero-length root label. */
*output = malloc (1);
if (!*output)
return IDNA_MALLOC_ERROR;
strcpy (*output, "");
return IDNA_SUCCESS;
}
if (DOTP (input[0]) && input[1] == 0)
{
/* Handle explicit zero-length root label. */
*output = malloc (2);
if (!*output)
return IDNA_MALLOC_ERROR;
strcpy (*output, ".");
return IDNA_SUCCESS;
}
*output = NULL;
do
{
end = start;
for (; *end && !DOTP (*end); end++)
;
if (*end == '\0' && start == end)
{
/* Handle explicit zero-length root label. */
buf[0] = '\0';
}
else
{
rc = idna_to_ascii_4i (start, end - start, buf, flags);
if (rc != IDNA_SUCCESS)
return rc;
}
if (out)
{
char *newp = realloc (out, strlen (out) + 1 + strlen (buf) + 1);
if (!newp)
{
free (out);
return IDNA_MALLOC_ERROR;
}
out = newp;
strcat (out, ".");
strcat (out, buf);
}
else
{
out = (char *) malloc (strlen (buf) + 1);
if (!out)
return IDNA_MALLOC_ERROR;
strcpy (out, buf);
}
start = end + 1;
}
while (*end);
*output = out;
return IDNA_SUCCESS;
}
/**
* idna_to_ascii_8z:
* @input: zero terminated input UTF-8 string.
* @output: pointer to newly allocated output string.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert UTF-8 domain name to ASCII string. The domain name may
* contain several labels, separated by dots. The output buffer must
* be deallocated by the caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_ascii_8z (const char *input, char **output, int flags)
{
uint32_t *ucs4;
size_t ucs4len;
int rc;
ucs4 = stringprep_utf8_to_ucs4 (input, -1, &ucs4len);
if (!ucs4)
return IDNA_ICONV_ERROR;
rc = idna_to_ascii_4z (ucs4, output, flags);
free (ucs4);
return rc;
}
/**
* idna_to_ascii_lz:
* @input: zero terminated input UTF-8 string.
* @output: pointer to newly allocated output string.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert domain name in the locale's encoding to ASCII string. The
* domain name may contain several labels, separated by dots. The
* output buffer must be deallocated by the caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_ascii_lz (const char *input, char **output, int flags)
{
char *utf8;
int rc;
utf8 = stringprep_locale_to_utf8 (input);
if (!utf8)
return IDNA_ICONV_ERROR;
rc = idna_to_ascii_8z (utf8, output, flags);
free (utf8);
return rc;
}
/**
* idna_to_unicode_4z4z:
* @input: zero-terminated Unicode string.
* @output: pointer to newly allocated output Unicode string.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert possibly ACE encoded domain name in UCS-4 format into a
* UCS-4 string. The domain name may contain several labels,
* separated by dots. The output buffer must be deallocated by the
* caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_unicode_4z4z (const uint32_t * input, uint32_t ** output, int flags)
{
const uint32_t *start = input;
const uint32_t *end = input;
uint32_t *buf;
size_t buflen;
uint32_t *out = NULL;
size_t outlen = 0;
*output = NULL;
do
{
end = start;
for (; *end && !DOTP (*end); end++)
;
buflen = end - start;
buf = malloc (sizeof (buf[0]) * (buflen + 1));
if (!buf)
return IDNA_MALLOC_ERROR;
idna_to_unicode_44i (start, end - start, buf, &buflen, flags);
/* don't check return value as per specification! */
if (out)
{
uint32_t *newp = realloc (out,
sizeof (out[0])
* (outlen + 1 + buflen + 1));
if (!newp)
{
free (buf);
free (out);
return IDNA_MALLOC_ERROR;
}
out = newp;
out[outlen++] = 0x002E; /* '.' (full stop) */
memcpy (out + outlen, buf, sizeof (buf[0]) * buflen);
outlen += buflen;
out[outlen] = 0x0;
free (buf);
}
else
{
out = buf;
outlen = buflen;
out[outlen] = 0x0;
}
start = end + 1;
}
while (*end);
*output = out;
return IDNA_SUCCESS;
}
/**
* idna_to_unicode_8z4z:
* @input: zero-terminated UTF-8 string.
* @output: pointer to newly allocated output Unicode string.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert possibly ACE encoded domain name in UTF-8 format into a
* UCS-4 string. The domain name may contain several labels,
* separated by dots. The output buffer must be deallocated by the
* caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_unicode_8z4z (const char *input, uint32_t ** output, int flags)
{
uint32_t *ucs4;
size_t ucs4len;
int rc;
ucs4 = stringprep_utf8_to_ucs4 (input, -1, &ucs4len);
if (!ucs4)
return IDNA_ICONV_ERROR;
rc = idna_to_unicode_4z4z (ucs4, output, flags);
free (ucs4);
return rc;
}
/**
* idna_to_unicode_8z8z:
* @input: zero-terminated UTF-8 string.
* @output: pointer to newly allocated output UTF-8 string.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert possibly ACE encoded domain name in UTF-8 format into a
* UTF-8 string. The domain name may contain several labels,
* separated by dots. The output buffer must be deallocated by the
* caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_unicode_8z8z (const char *input, char **output, int flags)
{
uint32_t *ucs4;
int rc;
rc = idna_to_unicode_8z4z (input, &ucs4, flags);
*output = stringprep_ucs4_to_utf8 (ucs4, -1, NULL, NULL);
free (ucs4);
if (!*output)
return IDNA_ICONV_ERROR;
return rc;
}
/**
* idna_to_unicode_8zlz:
* @input: zero-terminated UTF-8 string.
* @output: pointer to newly allocated output string encoded in the
* current locale's character set.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert possibly ACE encoded domain name in UTF-8 format into a
* string encoded in the current locale's character set. The domain
* name may contain several labels, separated by dots. The output
* buffer must be deallocated by the caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_unicode_8zlz (const char *input, char **output, int flags)
{
char *utf8;
int rc;
rc = idna_to_unicode_8z8z (input, &utf8, flags);
*output = stringprep_utf8_to_locale (utf8);
free (utf8);
if (!*output)
return IDNA_ICONV_ERROR;
return rc;
}
/**
* idna_to_unicode_lzlz:
* @input: zero-terminated string encoded in the current locale's
* character set.
* @output: pointer to newly allocated output string encoded in the
* current locale's character set.
* @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
*
* Convert possibly ACE encoded domain name in the locale's character
* set into a string encoded in the current locale's character set.
* The domain name may contain several labels, separated by dots. The
* output buffer must be deallocated by the caller.
*
* Return value: Returns IDNA_SUCCESS on success, or error code.
**/
int
idna_to_unicode_lzlz (const char *input, char **output, int flags)
{
char *utf8;
int rc;
utf8 = stringprep_locale_to_utf8 (input);
if (!utf8)
return IDNA_ICONV_ERROR;
rc = idna_to_unicode_8zlz (utf8, output, flags);
free (utf8);
return rc;
}
/**
* IDNA_ACE_PREFIX
*
* The IANA allocated prefix to use for IDNA. "xn--"
*/
/**
* Idna_rc:
* @IDNA_SUCCESS: Successful operation. This value is guaranteed to
* always be zero, the remaining ones are only guaranteed to hold
* non-zero values, for logical comparison purposes.
* @IDNA_STRINGPREP_ERROR: Error during string preparation.
* @IDNA_PUNYCODE_ERROR: Error during punycode operation.
* @IDNA_CONTAINS_NON_LDH: For IDNA_USE_STD3_ASCII_RULES, indicate that
* the string contains non-LDH ASCII characters.
* @IDNA_CONTAINS_MINUS: For IDNA_USE_STD3_ASCII_RULES, indicate that
* the string contains a leading or trailing hyphen-minus (U+002D).
* @IDNA_INVALID_LENGTH: The final output string is not within the
* (inclusive) range 1 to 63 characters.
* @IDNA_NO_ACE_PREFIX: The string does not contain the ACE prefix
* (for ToUnicode).
* @IDNA_ROUNDTRIP_VERIFY_ERROR: The ToASCII operation on output
* string does not equal the input.
* @IDNA_CONTAINS_ACE_PREFIX: The input contains the ACE prefix (for
* ToASCII).
* @IDNA_ICONV_ERROR: Could not convert string in locale encoding.
* @IDNA_MALLOC_ERROR: Could not allocate buffer (this is typically a
* fatal error).
* @IDNA_DLOPEN_ERROR: Could not dlopen the libcidn DSO (only used
* internally in libc).
*
* Enumerated return codes of idna_to_ascii_4i(),
* idna_to_unicode_44i() functions (and functions derived from those
* functions). The value 0 is guaranteed to always correspond to
* success.
*/
/**
* Idna_flags:
* @IDNA_ALLOW_UNASSIGNED: Don't reject strings containing unassigned
* Unicode code points.
* @IDNA_USE_STD3_ASCII_RULES: Validate strings according to STD3
* rules (i.e., normal host name rules).
*
* Flags to pass to idna_to_ascii_4i(), idna_to_unicode_44i() etc.
*/

View File

@ -1,96 +0,0 @@
/* idna.h Declarations for IDNA.
* Copyright (C) 2002, 2003, 2004 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _IDNA_H
#define _IDNA_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h> /* size_t */
#include <stdint.h> /* uint32_t */
/* Error codes. */
typedef enum
{
IDNA_SUCCESS = 0,
IDNA_STRINGPREP_ERROR = 1,
IDNA_PUNYCODE_ERROR = 2,
IDNA_CONTAINS_NON_LDH = 3,
/* Workaround typo in earlier versions. */
IDNA_CONTAINS_LDH = IDNA_CONTAINS_NON_LDH,
IDNA_CONTAINS_MINUS = 4,
IDNA_INVALID_LENGTH = 5,
IDNA_NO_ACE_PREFIX = 6,
IDNA_ROUNDTRIP_VERIFY_ERROR = 7,
IDNA_CONTAINS_ACE_PREFIX = 8,
IDNA_ICONV_ERROR = 9,
/* Internal errors. */
IDNA_MALLOC_ERROR = 201,
IDNA_DLOPEN_ERROR = 202
} Idna_rc;
/* IDNA flags */
typedef enum
{
IDNA_ALLOW_UNASSIGNED = 0x0001,
IDNA_USE_STD3_ASCII_RULES = 0x0002
} Idna_flags;
#ifndef IDNA_ACE_PREFIX
#define IDNA_ACE_PREFIX "xn--"
#endif
/* Core functions */
extern int idna_to_ascii_4i (const uint32_t * in, size_t inlen,
char *out, int flags);
extern int idna_to_unicode_44i (const uint32_t * in, size_t inlen,
uint32_t * out, size_t * outlen, int flags);
/* Wrappers that handle several labels */
extern int idna_to_ascii_4z (const uint32_t * input,
char **output, int flags);
extern int idna_to_ascii_8z (const char *input, char **output, int flags);
extern int idna_to_ascii_lz (const char *input, char **output, int flags);
extern int idna_to_unicode_4z4z (const uint32_t * input,
uint32_t ** output, int flags);
extern int idna_to_unicode_8z4z (const char *input,
uint32_t ** output, int flags);
extern int idna_to_unicode_8z8z (const char *input,
char **output, int flags);
extern int idna_to_unicode_8zlz (const char *input,
char **output, int flags);
extern int idna_to_unicode_lzlz (const char *input,
char **output, int flags);
#ifdef __cplusplus
}
#endif
#endif /* _PUNYCODE_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,308 +0,0 @@
/* profiles.c Definitions of stringprep profiles.
* Copyright (C) 2002, 2003, 2004 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
#include "stringprep.h"
const Stringprep_profiles stringprep_profiles[] = {
{"Nameprep", stringprep_nameprep},
{"KRBprep", stringprep_kerberos5}, /* Deprecate? */
{"Nodeprep", stringprep_xmpp_nodeprep},
{"Resourceprep", stringprep_xmpp_resourceprep},
{"plain", stringprep_plain}, /* sasl-anon-00. */
{"trace", stringprep_trace}, /* sasl-anon-01,02. */
{"SASLprep", stringprep_saslprep},
{"ISCSIprep", stringprep_iscsi}, /* Obsolete. */
{"iSCSI", stringprep_iscsi}, /* IANA. */
{NULL, NULL}
};
const Stringprep_profile stringprep_nameprep[] = {
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
{STRINGPREP_NFKC, 0, 0},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_7},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, ~STRINGPREP_NO_BIDI,
stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, 0, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, 0, stringprep_rfc3454_D_2},
{STRINGPREP_UNASSIGNED_TABLE, ~STRINGPREP_NO_UNASSIGNED,
stringprep_rfc3454_A_1},
{0}
};
const Stringprep_profile stringprep_kerberos5[] = {
/* XXX this is likely to be wrong as the specification is
a rough draft. */
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_3},
{STRINGPREP_NFKC, 0, 0},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_7},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, ~STRINGPREP_NO_BIDI,
stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, 0, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, 0, stringprep_rfc3454_D_2},
{STRINGPREP_UNASSIGNED_TABLE, ~STRINGPREP_NO_UNASSIGNED,
stringprep_rfc3454_A_1},
{0}
};
const Stringprep_table_element stringprep_xmpp_nodeprep_prohibit[] = {
{0x000022}, /* #x22 (") */
{0x000026}, /* #x26 (&) */
{0x000027}, /* #x27 (') */
{0x00002F}, /* #x2F (/) */
{0x00003A}, /* #x3A (:) */
{0x00003C}, /* #x3C (<) */
{0x00003E}, /* #x3E (>) */
{0x000040}, /* #x40 (@) */
{0}
};
const Stringprep_profile stringprep_xmpp_nodeprep[] = {
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
{STRINGPREP_NFKC, 0, 0},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_7},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_xmpp_nodeprep_prohibit},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, 0, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, 0, stringprep_rfc3454_D_2},
{STRINGPREP_UNASSIGNED_TABLE, ~STRINGPREP_NO_UNASSIGNED,
stringprep_rfc3454_A_1},
{0}
};
const Stringprep_profile stringprep_xmpp_resourceprep[] = {
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
{STRINGPREP_NFKC, 0, 0},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_7},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_2},
{STRINGPREP_UNASSIGNED_TABLE, ~STRINGPREP_NO_UNASSIGNED,
stringprep_rfc3454_A_1},
{0}
};
const Stringprep_profile stringprep_plain[] = {
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_2},
{0}
};
const Stringprep_profile stringprep_trace[] = {
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_2},
{0}
};
const Stringprep_table_element stringprep_iscsi_prohibit[] = {
{0x0000}, /* [ASCII CONTROL CHARACTERS and SPACE through ,] */
{0x0001},
{0x0002},
{0x0003},
{0x0004},
{0x0005},
{0x0006},
{0x0007},
{0x0008},
{0x0009},
{0x000A},
{0x000B},
{0x000C},
{0x000D},
{0x000E},
{0x000F},
{0x0010},
{0x0011},
{0x0012},
{0x0013},
{0x0014},
{0x0015},
{0x0016},
{0x0017},
{0x0018},
{0x0019},
{0x001A},
{0x001B},
{0x001C},
{0x001D},
{0x001E},
{0x001F},
{0x0020},
{0x0021},
{0x0022},
{0x0023},
{0x0024},
{0x0025},
{0x0026},
{0x0027},
{0x0028},
{0x0029},
{0x002A},
{0x002B},
{0x002C},
{0x002F}, /* [ASCII /] */
{0x003B}, /* [ASCII ; through @] */
{0x003C},
{0x003D},
{0x003E},
{0x003F},
{0x0040},
{0x005B}, /* [ASCII [ through `] */
{0x005C},
{0x005D},
{0x005E},
{0x005F},
{0x0060},
{0x007B}, /* [ASCII { through DEL] */
{0x007C},
{0x007D},
{0x007E},
{0x007F},
{0x3002}, /* ideographic full stop */
{0}
};
const Stringprep_profile stringprep_iscsi[] = {
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
{STRINGPREP_NFKC, 0, 0},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_iscsi_prohibit},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_2},
{STRINGPREP_UNASSIGNED_TABLE, ~STRINGPREP_NO_UNASSIGNED,
stringprep_rfc3454_A_1},
{0}
};
const Stringprep_table_element stringprep_saslprep_space_map[] = {
{0x0000A0, 0, {0x0020}}, /* 00A0; NO-BREAK SPACE */
{0x001680, 0, {0x0020}}, /* 1680; OGHAM SPACE MARK */
{0x002000, 0, {0x0020}}, /* 2000; EN QUAD */
{0x002001, 0, {0x0020}}, /* 2001; EM QUAD */
{0x002002, 0, {0x0020}}, /* 2002; EN SPACE */
{0x002003, 0, {0x0020}}, /* 2003; EM SPACE */
{0x002004, 0, {0x0020}}, /* 2004; THREE-PER-EM SPACE */
{0x002005, 0, {0x0020}}, /* 2005; FOUR-PER-EM SPACE */
{0x002006, 0, {0x0020}}, /* 2006; SIX-PER-EM SPACE */
{0x002007, 0, {0x0020}}, /* 2007; FIGURE SPACE */
{0x002008, 0, {0x0020}}, /* 2008; PUNCTUATION SPACE */
{0x002009, 0, {0x0020}}, /* 2009; THIN SPACE */
{0x00200A, 0, {0x0020}}, /* 200A; HAIR SPACE */
{0x00200B, 0, {0x0020}}, /* 200B; ZERO WIDTH SPACE */
{0x00202F, 0, {0x0020}}, /* 202F; NARROW NO-BREAK SPACE */
{0x00205F, 0, {0x0020}}, /* 205F; MEDIUM MATHEMATICAL SPACE */
{0x003000, 0, {0x0020}}, /* 3000; IDEOGRAPHIC SPACE */
{0}
};
const Stringprep_profile stringprep_saslprep[] = {
{STRINGPREP_MAP_TABLE, 0, stringprep_saslprep_space_map},
{STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
{STRINGPREP_NFKC, 0, 0},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_1_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_1},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_2_2},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_3},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_4},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_5},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_6},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_7},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_9},
{STRINGPREP_BIDI, 0, 0},
{STRINGPREP_BIDI_PROHIBIT_TABLE, 0, stringprep_rfc3454_C_8},
{STRINGPREP_BIDI_RAL_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_1},
{STRINGPREP_BIDI_L_TABLE, ~STRINGPREP_NO_BIDI, stringprep_rfc3454_D_2},
{STRINGPREP_UNASSIGNED_TABLE, ~STRINGPREP_NO_UNASSIGNED,
stringprep_rfc3454_A_1},
{0}
};

View File

@ -1,454 +0,0 @@
/* punycode.c Implementation of punycode used to ASCII encode IDN's.
* Copyright (C) 2002, 2003 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* This file is derived from RFC 3492bis written by Adam M. Costello.
*
* Disclaimer and license: Regarding this entire document or any
* portion of it (including the pseudocode and C code), the author
* makes no guarantees and is not responsible for any damage resulting
* from its use. The author grants irrevocable permission to anyone
* to use, modify, and distribute it in any way that does not diminish
* the rights of anyone else to use, modify, and distribute it,
* provided that redistributed derivative works do not contain
* misleading author or version information. Derivative works need
* not be licensed under similar terms.
*
* Copyright (C) The Internet Society (2003). All Rights Reserved.
*
* This document and translations of it may be copied and furnished to
* others, and derivative works that comment on or otherwise explain it
* or assist in its implementation may be prepared, copied, published
* and distributed, in whole or in part, without restriction of any
* kind, provided that the above copyright notice and this paragraph are
* included on all such copies and derivative works. However, this
* document itself may not be modified in any way, such as by removing
* the copyright notice or references to the Internet Society or other
* Internet organizations, except as needed for the purpose of
* developing Internet standards in which case the procedures for
* copyrights defined in the Internet Standards process must be
* followed, or as required to translate it into languages other than
* English.
*
* The limited permissions granted above are perpetual and will not be
* revoked by the Internet Society or its successors or assigns.
*
* This document and the information contained herein is provided on an
* "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
* TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
* HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <string.h>
#include "punycode.h"
/*** Bootstring parameters for Punycode ***/
enum
{ base = 36, tmin = 1, tmax = 26, skew = 38, damp = 700,
initial_bias = 72, initial_n = 0x80, delimiter = 0x2D
};
/* basic(cp) tests whether cp is a basic code point: */
#define basic(cp) ((punycode_uint)(cp) < 0x80)
/* delim(cp) tests whether cp is a delimiter: */
#define delim(cp) ((cp) == delimiter)
/* decode_digit(cp) returns the numeric value of a basic code */
/* point (for use in representing integers) in the range 0 to */
/* base-1, or base if cp does not represent a value. */
static punycode_uint
decode_digit (punycode_uint cp)
{
return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 :
cp - 97 < 26 ? cp - 97 : base;
}
/* encode_digit(d,flag) returns the basic code point whose value */
/* (when used for representing integers) is d, which needs to be in */
/* the range 0 to base-1. The lowercase form is used unless flag is */
/* nonzero, in which case the uppercase form is used. The behavior */
/* is undefined if flag is nonzero and digit d has no uppercase form. */
static char
encode_digit (punycode_uint d, int flag)
{
return d + 22 + 75 * (d < 26) - ((flag != 0) << 5);
/* 0..25 map to ASCII a..z or A..Z */
/* 26..35 map to ASCII 0..9 */
}
/* flagged(bcp) tests whether a basic code point is flagged */
/* (uppercase). The behavior is undefined if bcp is not a */
/* basic code point. */
#define flagged(bcp) ((punycode_uint)(bcp) - 65 < 26)
/* encode_basic(bcp,flag) forces a basic code point to lowercase */
/* if flag is zero, uppercase if flag is nonzero, and returns */
/* the resulting code point. The code point is unchanged if it */
/* is caseless. The behavior is undefined if bcp is not a basic */
/* code point. */
static char
encode_basic (punycode_uint bcp, int flag)
{
bcp -= (bcp - 97 < 26) << 5;
return bcp + ((!flag && (bcp - 65 < 26)) << 5);
}
/*** Platform-specific constants ***/
/* maxint is the maximum value of a punycode_uint variable: */
static const punycode_uint maxint = -1;
/* Because maxint is unsigned, -1 becomes the maximum value. */
/*** Bias adaptation function ***/
static punycode_uint
adapt (punycode_uint delta, punycode_uint numpoints, int firsttime)
{
punycode_uint k;
delta = firsttime ? delta / damp : delta >> 1;
/* delta >> 1 is a faster way of doing delta / 2 */
delta += delta / numpoints;
for (k = 0; delta > ((base - tmin) * tmax) / 2; k += base)
{
delta /= base - tmin;
}
return k + (base - tmin + 1) * delta / (delta + skew);
}
/*** Main encode function ***/
/**
* punycode_encode:
* @input_length: The number of code points in the @input array and
* the number of flags in the @case_flags array.
* @input: An array of code points. They are presumed to be Unicode
* code points, but that is not strictly REQUIRED. The array
* contains code points, not code units. UTF-16 uses code units
* D800 through DFFF to refer to code points 10000..10FFFF. The
* code points D800..DFFF do not occur in any valid Unicode string.
* The code points that can occur in Unicode strings (0..D7FF and
* E000..10FFFF) are also called Unicode scalar values.
* @case_flags: A %NULL pointer or an array of boolean values parallel
* to the @input array. Nonzero (true, flagged) suggests that the
* corresponding Unicode character be forced to uppercase after
* being decoded (if possible), and zero (false, unflagged) suggests
* that it be forced to lowercase (if possible). ASCII code points
* (0..7F) are encoded literally, except that ASCII letters are
* forced to uppercase or lowercase according to the corresponding
* case flags. If @case_flags is a %NULL pointer then ASCII letters
* are left as they are, and other code points are treated as
* unflagged.
* @output_length: The caller passes in the maximum number of ASCII
* code points that it can receive. On successful return it will
* contain the number of ASCII code points actually output.
* @output: An array of ASCII code points. It is *not*
* null-terminated; it will contain zeros if and only if the @input
* contains zeros. (Of course the caller can leave room for a
* terminator and add one if needed.)
*
* Converts a sequence of code points (presumed to be Unicode code
* points) to Punycode.
*
* Return value: The return value can be any of the punycode_status
* values defined above except %punycode_bad_input. If not
* %punycode_success, then @output_size and @output might contain
* garbage.
**/
int
punycode_encode (size_t input_length,
const punycode_uint input[],
const unsigned char case_flags[],
size_t * output_length, char output[])
{
punycode_uint input_len, n, delta, h, b, bias, j, m, q, k, t;
size_t out, max_out;
/* The Punycode spec assumes that the input length is the same type */
/* of integer as a code point, so we need to convert the size_t to */
/* a punycode_uint, which could overflow. */
if (input_length > maxint)
return punycode_overflow;
input_len = (punycode_uint) input_length;
/* Initialize the state: */
n = initial_n;
delta = 0;
out = 0;
max_out = *output_length;
bias = initial_bias;
/* Handle the basic code points: */
for (j = 0; j < input_len; ++j)
{
if (basic (input[j]))
{
if (max_out - out < 2)
return punycode_big_output;
output[out++] = case_flags ?
encode_basic (input[j], case_flags[j]) : (char) input[j];
}
/* else if (input[j] < n) return punycode_bad_input; */
/* (not needed for Punycode with unsigned code points) */
}
h = b = (punycode_uint) out;
/* cannot overflow because out <= input_len <= maxint */
/* h is the number of code points that have been handled, b is the */
/* number of basic code points, and out is the number of ASCII code */
/* points that have been output. */
if (b > 0)
output[out++] = delimiter;
/* Main encoding loop: */
while (h < input_len)
{
/* All non-basic code points < n have been */
/* handled already. Find the next larger one: */
for (m = maxint, j = 0; j < input_len; ++j)
{
/* if (basic(input[j])) continue; */
/* (not needed for Punycode) */
if (input[j] >= n && input[j] < m)
m = input[j];
}
/* Increase delta enough to advance the decoder's */
/* <n,i> state to <m,0>, but guard against overflow: */
if (m - n > (maxint - delta) / (h + 1))
return punycode_overflow;
delta += (m - n) * (h + 1);
n = m;
for (j = 0; j < input_len; ++j)
{
/* Punycode does not need to check whether input[j] is basic: */
if (input[j] < n /* || basic(input[j]) */ )
{
if (++delta == 0)
return punycode_overflow;
}
if (input[j] == n)
{
/* Represent delta as a generalized variable-length integer: */
for (q = delta, k = base;; k += base)
{
if (out >= max_out)
return punycode_big_output;
t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */
k >= bias + tmax ? tmax : k - bias;
if (q < t)
break;
output[out++] = encode_digit (t + (q - t) % (base - t), 0);
q = (q - t) / (base - t);
}
output[out++] = encode_digit (q, case_flags && case_flags[j]);
bias = adapt (delta, h + 1, h == b);
delta = 0;
++h;
}
}
++delta, ++n;
}
*output_length = out;
return punycode_success;
}
/*** Main decode function ***/
/**
* punycode_decode:
* @input_length: The number of ASCII code points in the @input array.
* @input: An array of ASCII code points (0..7F).
* @output_length: The caller passes in the maximum number of code
* points that it can receive into the @output array (which is also
* the maximum number of flags that it can receive into the
* @case_flags array, if @case_flags is not a %NULL pointer). On
* successful return it will contain the number of code points
* actually output (which is also the number of flags actually
* output, if case_flags is not a null pointer). The decoder will
* never need to output more code points than the number of ASCII
* code points in the input, because of the way the encoding is
* defined. The number of code points output cannot exceed the
* maximum possible value of a punycode_uint, even if the supplied
* @output_length is greater than that.
* @output: An array of code points like the input argument of
* punycode_encode() (see above).
* @case_flags: A %NULL pointer (if the flags are not needed by the
* caller) or an array of boolean values parallel to the @output
* array. Nonzero (true, flagged) suggests that the corresponding
* Unicode character be forced to uppercase by the caller (if
* possible), and zero (false, unflagged) suggests that it be forced
* to lowercase (if possible). ASCII code points (0..7F) are output
* already in the proper case, but their flags will be set
* appropriately so that applying the flags would be harmless.
*
* Converts Punycode to a sequence of code points (presumed to be
* Unicode code points).
*
* Return value: The return value can be any of the punycode_status
* values defined above. If not %punycode_success, then
* @output_length, @output, and @case_flags might contain garbage.
*
**/
int
punycode_decode (size_t input_length,
const char input[],
size_t * output_length,
punycode_uint output[], unsigned char case_flags[])
{
punycode_uint n, out, i, max_out, bias, oldi, w, k, digit, t;
size_t b, j, in;
/* Initialize the state: */
n = initial_n;
out = i = 0;
max_out = *output_length > maxint ? maxint
: (punycode_uint) * output_length;
bias = initial_bias;
/* Handle the basic code points: Let b be the number of input code */
/* points before the last delimiter, or 0 if there is none, then */
/* copy the first b code points to the output. */
for (b = j = 0; j < input_length; ++j)
if (delim (input[j]))
b = j;
if (b > max_out)
return punycode_big_output;
for (j = 0; j < b; ++j)
{
if (case_flags)
case_flags[out] = flagged (input[j]);
if (!basic (input[j]))
return punycode_bad_input;
output[out++] = input[j];
}
/* Main decoding loop: Start just after the last delimiter if any */
/* basic code points were copied; start at the beginning otherwise. */
for (in = b > 0 ? b + 1 : 0; in < input_length; ++out)
{
/* in is the index of the next ASCII code point to be consumed, */
/* and out is the number of code points in the output array. */
/* Decode a generalized variable-length integer into delta, */
/* which gets added to i. The overflow checking is easier */
/* if we increase i as we go, then subtract off its starting */
/* value at the end to obtain delta. */
for (oldi = i, w = 1, k = base;; k += base)
{
if (in >= input_length)
return punycode_bad_input;
digit = decode_digit (input[in++]);
if (digit >= base)
return punycode_bad_input;
if (digit > (maxint - i) / w)
return punycode_overflow;
i += digit * w;
t = k <= bias /* + tmin */ ? tmin : /* +tmin not needed */
k >= bias + tmax ? tmax : k - bias;
if (digit < t)
break;
if (w > maxint / (base - t))
return punycode_overflow;
w *= (base - t);
}
bias = adapt (i - oldi, out + 1, oldi == 0);
/* i was supposed to wrap around from out+1 to 0, */
/* incrementing n each time, so we'll fix that now: */
if (i / (out + 1) > maxint - n)
return punycode_overflow;
n += i / (out + 1);
i %= (out + 1);
/* Insert n at position i of the output: */
/* not needed for Punycode: */
/* if (basic(n)) return punycode_invalid_input; */
if (out >= max_out)
return punycode_big_output;
if (case_flags)
{
memmove (case_flags + i + 1, case_flags + i, out - i);
/* Case of last ASCII code point determines case flag: */
case_flags[i] = flagged (input[in - 1]);
}
memmove (output + i + 1, output + i, (out - i) * sizeof *output);
output[i++] = n;
}
*output_length = (size_t) out;
/* cannot overflow because out <= old value of *output_length */
return punycode_success;
}
/**
* punycode_uint
*
* Unicode code point data type, this is always a 32 bit unsigned
* integer.
*/
/**
* Punycode_status
* @PUNYCODE_SUCCESS: Successful operation. This value is guaranteed
* to always be zero, the remaining ones are only guaranteed to hold
* non-zero values, for logical comparison purposes.
* @PUNYCODE_BAD_INPUT: Input is invalid.
* @PUNYCODE_BIG_OUTPUT: Output would exceed the space provided.
* @PUNYCODE_OVERFLOW: Input needs wider integers to process.
*
* Enumerated return codes of punycode_encode() and punycode_decode().
* The value 0 is guaranteed to always correspond to success.
*/

View File

@ -1,214 +0,0 @@
/* punycode.h Declarations for punycode functions.
* Copyright (C) 2002, 2003 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
/*
* This file is derived from RFC 3492bis written by Adam M. Costello.
*
* Disclaimer and license: Regarding this entire document or any
* portion of it (including the pseudocode and C code), the author
* makes no guarantees and is not responsible for any damage resulting
* from its use. The author grants irrevocable permission to anyone
* to use, modify, and distribute it in any way that does not diminish
* the rights of anyone else to use, modify, and distribute it,
* provided that redistributed derivative works do not contain
* misleading author or version information. Derivative works need
* not be licensed under similar terms.
*
* Copyright (C) The Internet Society (2003). All Rights Reserved.
*
* This document and translations of it may be copied and furnished to
* others, and derivative works that comment on or otherwise explain it
* or assist in its implementation may be prepared, copied, published
* and distributed, in whole or in part, without restriction of any
* kind, provided that the above copyright notice and this paragraph are
* included on all such copies and derivative works. However, this
* document itself may not be modified in any way, such as by removing
* the copyright notice or references to the Internet Society or other
* Internet organizations, except as needed for the purpose of
* developing Internet standards in which case the procedures for
* copyrights defined in the Internet Standards process must be
* followed, or as required to translate it into languages other than
* English.
*
* The limited permissions granted above are perpetual and will not be
* revoked by the Internet Society or its successors or assigns.
*
* This document and the information contained herein is provided on an
* "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
* TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
* HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef _PUNYCODE_H
#define _PUNYCODE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h> /* size_t */
#include <stdint.h> /* uint32_t */
enum punycode_status
{
punycode_success = 0,
punycode_bad_input = 1, /* Input is invalid. */
punycode_big_output = 2, /* Output would exceed the space provided. */
punycode_overflow = 3 /* Wider integers needed to process input. */
};
typedef enum
{
PUNYCODE_SUCCESS = punycode_success,
PUNYCODE_BAD_INPUT = punycode_bad_input,
PUNYCODE_BIG_OUTPUT = punycode_big_output,
PUNYCODE_OVERFLOW = punycode_overflow
} Punycode_status;
/* punycode_uint needs to be unsigned and needs to be */
/* at least 26 bits wide. */
typedef uint32_t punycode_uint;
extern int punycode_encode (size_t input_length,
const punycode_uint input[],
const unsigned char case_flags[],
size_t * output_length, char output[]);
/*
punycode_encode() converts a sequence of code points (presumed to be
Unicode code points) to Punycode.
Input arguments (to be supplied by the caller):
input_length
The number of code points in the input array and the number
of flags in the case_flags array.
input
An array of code points. They are presumed to be Unicode
code points, but that is not strictly REQUIRED. The
array contains code points, not code units. UTF-16 uses
code units D800 through DFFF to refer to code points
10000..10FFFF. The code points D800..DFFF do not occur in
any valid Unicode string. The code points that can occur in
Unicode strings (0..D7FF and E000..10FFFF) are also called
Unicode scalar values.
case_flags
A null pointer or an array of boolean values parallel to
the input array. Nonzero (true, flagged) suggests that the
corresponding Unicode character be forced to uppercase after
being decoded (if possible), and zero (false, unflagged)
suggests that it be forced to lowercase (if possible).
ASCII code points (0..7F) are encoded literally, except that
ASCII letters are forced to uppercase or lowercase according
to the corresponding case flags. If case_flags is a null
pointer then ASCII letters are left as they are, and other
code points are treated as unflagged.
Output arguments (to be filled in by the function):
output
An array of ASCII code points. It is *not* null-terminated;
it will contain zeros if and only if the input contains
zeros. (Of course the caller can leave room for a
terminator and add one if needed.)
Input/output arguments (to be supplied by the caller and overwritten
by the function):
output_length
The caller passes in the maximum number of ASCII code points
that it can receive. On successful return it will contain
the number of ASCII code points actually output.
Return value:
Can be any of the punycode_status values defined above except
punycode_bad_input. If not punycode_success, then output_size
and output might contain garbage.
*/
extern int punycode_decode (size_t input_length,
const char input[],
size_t * output_length,
punycode_uint output[],
unsigned char case_flags[]);
/*
punycode_decode() converts Punycode to a sequence of code points
(presumed to be Unicode code points).
Input arguments (to be supplied by the caller):
input_length
The number of ASCII code points in the input array.
input
An array of ASCII code points (0..7F).
Output arguments (to be filled in by the function):
output
An array of code points like the input argument of
punycode_encode() (see above).
case_flags
A null pointer (if the flags are not needed by the caller)
or an array of boolean values parallel to the output array.
Nonzero (true, flagged) suggests that the corresponding
Unicode character be forced to uppercase by the caller (if
possible), and zero (false, unflagged) suggests that it
be forced to lowercase (if possible). ASCII code points
(0..7F) are output already in the proper case, but their
flags will be set appropriately so that applying the flags
would be harmless.
Input/output arguments (to be supplied by the caller and overwritten
by the function):
output_length
The caller passes in the maximum number of code points
that it can receive into the output array (which is also
the maximum number of flags that it can receive into the
case_flags array, if case_flags is not a null pointer). On
successful return it will contain the number of code points
actually output (which is also the number of flags actually
output, if case_flags is not a null pointer). The decoder
will never need to output more code points than the number
of ASCII code points in the input, because of the way the
encoding is defined. The number of code points output
cannot exceed the maximum possible value of a punycode_uint,
even if the supplied output_length is greater than that.
Return value:
Can be any of the punycode_status values defined above. If not
punycode_success, then output_length, output, and case_flags
might contain garbage.
*/
#ifdef __cplusplus
}
#endif
#endif /* _PUNYCODE_H */

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
libcidn=1

View File

@ -1,668 +0,0 @@
/* stringprep.c --- Core stringprep implementation.
* Copyright (C) 2002, 2003, 2004 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "stringprep.h"
static ssize_t
stringprep_find_character_in_table (uint32_t ucs4,
const Stringprep_table_element * table)
{
ssize_t i;
/* This is where typical uses of Libidn spends very close to all CPU
time and causes most cache misses. One could easily do a binary
search instead. Before rewriting this, I want hard evidence this
slowness is at all relevant in typical applications. (I don't
dispute optimization may improve matters significantly, I'm
mostly interested in having someone give real-world benchmark on
the impact of libidn.) */
for (i = 0; table[i].start || table[i].end; i++)
if (ucs4 >= table[i].start &&
ucs4 <= (table[i].end ? table[i].end : table[i].start))
return i;
return -1;
}
static ssize_t
stringprep_find_string_in_table (uint32_t * ucs4,
size_t ucs4len,
size_t * tablepos,
const Stringprep_table_element * table)
{
size_t j;
ssize_t pos;
for (j = 0; j < ucs4len; j++)
if ((pos = stringprep_find_character_in_table (ucs4[j], table)) != -1)
{
if (tablepos)
*tablepos = pos;
return j;
}
return -1;
}
static int
stringprep_apply_table_to_string (uint32_t * ucs4,
size_t * ucs4len,
size_t maxucs4len,
const Stringprep_table_element * table)
{
ssize_t pos;
size_t i, maplen;
while ((pos = stringprep_find_string_in_table (ucs4, *ucs4len,
&i, table)) != -1)
{
for (maplen = STRINGPREP_MAX_MAP_CHARS;
maplen > 0 && table[i].map[maplen - 1] == 0; maplen--)
;
if (*ucs4len - 1 + maplen >= maxucs4len)
return STRINGPREP_TOO_SMALL_BUFFER;
memmove (&ucs4[pos + maplen], &ucs4[pos + 1],
sizeof (uint32_t) * (*ucs4len - pos - 1));
memcpy (&ucs4[pos], table[i].map, sizeof (uint32_t) * maplen);
*ucs4len = *ucs4len - 1 + maplen;
}
return STRINGPREP_OK;
}
#define INVERTED(x) ((x) & ((~0UL) >> 1))
#define UNAPPLICAPLEFLAGS(flags, profileflags) \
((!INVERTED(profileflags) && !(profileflags & flags) && profileflags) || \
( INVERTED(profileflags) && (profileflags & flags)))
/**
* stringprep_4i:
* @ucs4: input/output array with string to prepare.
* @len: on input, length of input array with Unicode code points,
* on exit, length of output array with Unicode code points.
* @maxucs4len: maximum length of input/output array.
* @flags: stringprep profile flags, or 0.
* @profile: pointer to stringprep profile to use.
*
* Prepare the input UCS-4 string according to the stringprep profile,
* and write back the result to the input string.
*
* The input is not required to be zero terminated (@ucs4[@len] = 0).
* The output will not be zero terminated unless @ucs4[@len] = 0.
* Instead, see stringprep_4zi() if your input is zero terminated or
* if you want the output to be.
*
* Since the stringprep operation can expand the string, @maxucs4len
* indicate how large the buffer holding the string is. This function
* will not read or write to code points outside that size.
*
* The @flags are one of Stringprep_profile_flags, or 0.
*
* The @profile contain the instructions to perform. Your application
* can define new profiles, possibly re-using the generic stringprep
* tables that always will be part of the library, or use one of the
* currently supported profiles.
*
* Return value: Returns %STRINGPREP_OK iff successful, or an error code.
**/
int
stringprep_4i (uint32_t * ucs4, size_t * len, size_t maxucs4len,
Stringprep_profile_flags flags,
const Stringprep_profile * profile)
{
size_t i, j;
ssize_t k;
size_t ucs4len = *len;
int rc;
for (i = 0; profile[i].operation; i++)
{
switch (profile[i].operation)
{
case STRINGPREP_NFKC:
{
uint32_t *q = 0;
if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
break;
if (flags & STRINGPREP_NO_NFKC && !profile[i].flags)
/* Profile requires NFKC, but callee asked for no NFKC. */
return STRINGPREP_FLAG_ERROR;
q = stringprep_ucs4_nfkc_normalize (ucs4, ucs4len);
if (!q)
return STRINGPREP_NFKC_FAILED;
for (ucs4len = 0; q[ucs4len]; ucs4len++)
;
if (ucs4len >= maxucs4len)
{
free (q);
return STRINGPREP_TOO_SMALL_BUFFER;
}
memcpy (ucs4, q, ucs4len * sizeof (ucs4[0]));
free (q);
}
break;
case STRINGPREP_PROHIBIT_TABLE:
k = stringprep_find_string_in_table (ucs4, ucs4len,
NULL, profile[i].table);
if (k != -1)
return STRINGPREP_CONTAINS_PROHIBITED;
break;
case STRINGPREP_UNASSIGNED_TABLE:
if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
break;
if (flags & STRINGPREP_NO_UNASSIGNED)
{
k = stringprep_find_string_in_table
(ucs4, ucs4len, NULL, profile[i].table);
if (k != -1)
return STRINGPREP_CONTAINS_UNASSIGNED;
}
break;
case STRINGPREP_MAP_TABLE:
if (UNAPPLICAPLEFLAGS (flags, profile[i].flags))
break;
rc = stringprep_apply_table_to_string
(ucs4, &ucs4len, maxucs4len, profile[i].table);
if (rc != STRINGPREP_OK)
return rc;
break;
case STRINGPREP_BIDI_PROHIBIT_TABLE:
case STRINGPREP_BIDI_RAL_TABLE:
case STRINGPREP_BIDI_L_TABLE:
break;
case STRINGPREP_BIDI:
{
int done_prohibited = 0;
int done_ral = 0;
int done_l = 0;
int contains_ral = -1;
int contains_l = -1;
for (j = 0; profile[j].operation; j++)
if (profile[j].operation == STRINGPREP_BIDI_PROHIBIT_TABLE)
{
done_prohibited = 1;
k = stringprep_find_string_in_table (ucs4, ucs4len,
NULL,
profile[j].table);
if (k != -1)
return STRINGPREP_BIDI_CONTAINS_PROHIBITED;
}
else if (profile[j].operation == STRINGPREP_BIDI_RAL_TABLE)
{
done_ral = 1;
if (stringprep_find_string_in_table
(ucs4, ucs4len, NULL, profile[j].table) != -1)
contains_ral = j;
}
else if (profile[j].operation == STRINGPREP_BIDI_L_TABLE)
{
done_l = 1;
if (stringprep_find_string_in_table
(ucs4, ucs4len, NULL, profile[j].table) != -1)
contains_l = j;
}
if (!done_prohibited || !done_ral || !done_l)
return STRINGPREP_PROFILE_ERROR;
if (contains_ral != -1 && contains_l != -1)
return STRINGPREP_BIDI_BOTH_L_AND_RAL;
if (contains_ral != -1)
{
if (!(stringprep_find_character_in_table
(ucs4[0], profile[contains_ral].table) != -1 &&
stringprep_find_character_in_table
(ucs4[ucs4len - 1], profile[contains_ral].table) != -1))
return STRINGPREP_BIDI_LEADTRAIL_NOT_RAL;
}
}
break;
default:
return STRINGPREP_PROFILE_ERROR;
break;
}
}
*len = ucs4len;
return STRINGPREP_OK;
}
static int
stringprep_4zi_1 (uint32_t * ucs4, size_t ucs4len, size_t maxucs4len,
Stringprep_profile_flags flags,
const Stringprep_profile * profile)
{
int rc;
rc = stringprep_4i (ucs4, &ucs4len, maxucs4len, flags, profile);
if (rc != STRINGPREP_OK)
return rc;
if (ucs4len >= maxucs4len)
return STRINGPREP_TOO_SMALL_BUFFER;
ucs4[ucs4len] = 0;
return STRINGPREP_OK;
}
/**
* stringprep_4zi:
* @ucs4: input/output array with zero terminated string to prepare.
* @maxucs4len: maximum length of input/output array.
* @flags: stringprep profile flags, or 0.
* @profile: pointer to stringprep profile to use.
*
* Prepare the input zero terminated UCS-4 string according to the
* stringprep profile, and write back the result to the input string.
*
* Since the stringprep operation can expand the string, @maxucs4len
* indicate how large the buffer holding the string is. This function
* will not read or write to code points outside that size.
*
* The @flags are one of Stringprep_profile_flags, or 0.
*
* The @profile contain the instructions to perform. Your application
* can define new profiles, possibly re-using the generic stringprep
* tables that always will be part of the library, or use one of the
* currently supported profiles.
*
* Return value: Returns %STRINGPREP_OK iff successful, or an error code.
**/
int
stringprep_4zi (uint32_t * ucs4, size_t maxucs4len,
Stringprep_profile_flags flags,
const Stringprep_profile * profile)
{
size_t ucs4len;
for (ucs4len = 0; ucs4len < maxucs4len && ucs4[ucs4len] != 0; ucs4len++)
;
return stringprep_4zi_1 (ucs4, ucs4len, maxucs4len, flags, profile);
}
/**
* stringprep:
* @in: input/ouput array with string to prepare.
* @maxlen: maximum length of input/output array.
* @flags: stringprep profile flags, or 0.
* @profile: pointer to stringprep profile to use.
*
* Prepare the input zero terminated UTF-8 string according to the
* stringprep profile, and write back the result to the input string.
*
* Note that you must convert strings entered in the systems locale
* into UTF-8 before using this function, see
* stringprep_locale_to_utf8().
*
* Since the stringprep operation can expand the string, @maxlen
* indicate how large the buffer holding the string is. This function
* will not read or write to characters outside that size.
*
* The @flags are one of Stringprep_profile_flags, or 0.
*
* The @profile contain the instructions to perform. Your application
* can define new profiles, possibly re-using the generic stringprep
* tables that always will be part of the library, or use one of the
* currently supported profiles.
*
* Return value: Returns %STRINGPREP_OK iff successful, or an error code.
**/
int
stringprep (char *in,
size_t maxlen,
Stringprep_profile_flags flags,
const Stringprep_profile * profile)
{
int rc;
char *utf8 = NULL;
uint32_t *ucs4 = NULL;
size_t ucs4len, maxucs4len, adducs4len = 50;
do
{
free (ucs4);
ucs4 = stringprep_utf8_to_ucs4 (in, -1, &ucs4len);
maxucs4len = ucs4len + adducs4len;
uint32_t *newp = realloc (ucs4, maxucs4len * sizeof (uint32_t));
if (!newp)
{
free (ucs4);
return STRINGPREP_MALLOC_ERROR;
}
ucs4 = newp;
rc = stringprep_4i (ucs4, &ucs4len, maxucs4len, flags, profile);
adducs4len += 50;
}
while (rc == STRINGPREP_TOO_SMALL_BUFFER);
if (rc != STRINGPREP_OK)
{
free (ucs4);
return rc;
}
utf8 = stringprep_ucs4_to_utf8 (ucs4, ucs4len, 0, 0);
free (ucs4);
if (!utf8)
return STRINGPREP_MALLOC_ERROR;
if (strlen (utf8) >= maxlen)
{
free (utf8);
return STRINGPREP_TOO_SMALL_BUFFER;
}
strcpy (in, utf8); /* flawfinder: ignore */
free (utf8);
return STRINGPREP_OK;
}
/**
* stringprep_profile:
* @in: input array with UTF-8 string to prepare.
* @out: output variable with pointer to newly allocate string.
* @profile: name of stringprep profile to use.
* @flags: stringprep profile flags, or 0.
*
* Prepare the input zero terminated UTF-8 string according to the
* stringprep profile, and return the result in a newly allocated
* variable.
*
* Note that you must convert strings entered in the systems locale
* into UTF-8 before using this function, see
* stringprep_locale_to_utf8().
*
* The output @out variable must be deallocated by the caller.
*
* The @flags are one of Stringprep_profile_flags, or 0.
*
* The @profile specifies the name of the stringprep profile to use.
* It must be one of the internally supported stringprep profiles.
*
* Return value: Returns %STRINGPREP_OK iff successful, or an error code.
**/
int
stringprep_profile (const char *in,
char **out,
const char *profile, Stringprep_profile_flags flags)
{
const Stringprep_profiles *p;
char *str = NULL;
size_t len = strlen (in) + 1;
int rc;
for (p = &stringprep_profiles[0]; p->name; p++)
if (strcmp (p->name, profile) == 0)
break;
if (!p || !p->name || !p->tables)
return STRINGPREP_UNKNOWN_PROFILE;
do
{
free (str);
str = (char *) malloc (len);
if (str == NULL)
return STRINGPREP_MALLOC_ERROR;
strcpy (str, in);
rc = stringprep (str, len, flags, p->tables);
len += 50;
}
while (rc == STRINGPREP_TOO_SMALL_BUFFER);
if (rc == STRINGPREP_OK)
*out = str;
else
free (str);
return rc;
}
/*! \mainpage GNU Internationalized Domain Name Library
*
* \section intro Introduction
*
* GNU Libidn is an implementation of the Stringprep, Punycode and IDNA
* specifications defined by the IETF Internationalized Domain Names
* (IDN) working group, used for internationalized domain names. The
* package is available under the GNU Lesser General Public License.
*
* The library contains a generic Stringprep implementation that does
* Unicode 3.2 NFKC normalization, mapping and prohibitation of
* characters, and bidirectional character handling. Profiles for
* Nameprep, iSCSI, SASL and XMPP are included. Punycode and ASCII
* Compatible Encoding (ACE) via IDNA are supported. A mechanism to
* define Top-Level Domain (TLD) specific validation tables, and to
* compare strings against those tables, is included. Default tables
* for some TLDs are also included.
*
* The Stringprep API consists of two main functions, one for
* converting data from the system's native representation into UTF-8,
* and one function to perform the Stringprep processing. Adding a
* new Stringprep profile for your application within the API is
* straightforward. The Punycode API consists of one encoding
* function and one decoding function. The IDNA API consists of the
* ToASCII and ToUnicode functions, as well as an high-level interface
* for converting entire domain names to and from the ACE encoded
* form. The TLD API consists of one set of functions to extract the
* TLD name from a domain string, one set of functions to locate the
* proper TLD table to use based on the TLD name, and core functions
* to validate a string against a TLD table, and some utility wrappers
* to perform all the steps in one call.
*
* The library is used by, e.g., GNU SASL and Shishi to process user
* names and passwords. Libidn can be built into GNU Libc to enable a
* new system-wide getaddrinfo() flag for IDN processing.
*
* Libidn is developed for the GNU/Linux system, but runs on over 20 Unix
* platforms (including Solaris, IRIX, AIX, and Tru64) and Windows.
* Libidn is written in C and (parts of) the API is accessible from C,
* C++, Emacs Lisp, Python and Java.
*
* The project web page:\n
* http://www.gnu.org/software/libidn/
*
* The software archive:\n
* ftp://alpha.gnu.org/pub/gnu/libidn/
*
* For more information see:\n
* http://www.ietf.org/html.charters/idn-charter.html\n
* http://www.ietf.org/rfc/rfc3454.txt (stringprep specification)\n
* http://www.ietf.org/rfc/rfc3490.txt (idna specification)\n
* http://www.ietf.org/rfc/rfc3491.txt (nameprep specification)\n
* http://www.ietf.org/rfc/rfc3492.txt (punycode specification)\n
* http://www.ietf.org/internet-drafts/draft-ietf-ips-iscsi-string-prep-04.txt\n
* http://www.ietf.org/internet-drafts/draft-ietf-krb-wg-utf8-profile-01.txt\n
* http://www.ietf.org/internet-drafts/draft-ietf-sasl-anon-00.txt\n
* http://www.ietf.org/internet-drafts/draft-ietf-sasl-saslprep-00.txt\n
* http://www.ietf.org/internet-drafts/draft-ietf-xmpp-nodeprep-01.txt\n
* http://www.ietf.org/internet-drafts/draft-ietf-xmpp-resourceprep-01.txt\n
*
* Further information and paid contract development:\n
* Simon Josefsson <simon@josefsson.org>
*
* \section examples Examples
*
* \include example.c
* \include example3.c
* \include example4.c
* \include example5.c
*/
/**
* STRINGPREP_VERSION
*
* String defined via CPP denoting the header file version number.
* Used together with stringprep_check_version() to verify header file
* and run-time library consistency.
*/
/**
* STRINGPREP_MAX_MAP_CHARS
*
* Maximum number of code points that can replace a single code point,
* during stringprep mapping.
*/
/**
* Stringprep_rc:
* @STRINGPREP_OK: Successful operation. This value is guaranteed to
* always be zero, the remaining ones are only guaranteed to hold
* non-zero values, for logical comparison purposes.
* @STRINGPREP_CONTAINS_UNASSIGNED: String contain unassigned Unicode
* code points, which is forbidden by the profile.
* @STRINGPREP_CONTAINS_PROHIBITED: String contain code points
* prohibited by the profile.
* @STRINGPREP_BIDI_BOTH_L_AND_RAL: String contain code points with
* conflicting bidirectional category.
* @STRINGPREP_BIDI_LEADTRAIL_NOT_RAL: Leading and trailing character
* in string not of proper bidirectional category.
* @STRINGPREP_BIDI_CONTAINS_PROHIBITED: Contains prohibited code
* points detected by bidirectional code.
* @STRINGPREP_TOO_SMALL_BUFFER: Buffer handed to function was too
* small. This usually indicate a problem in the calling
* application.
* @STRINGPREP_PROFILE_ERROR: The stringprep profile was inconsistent.
* This usually indicate an internal error in the library.
* @STRINGPREP_FLAG_ERROR: The supplied flag conflicted with profile.
* This usually indicate a problem in the calling application.
* @STRINGPREP_UNKNOWN_PROFILE: The supplied profile name was not
* known to the library.
* @STRINGPREP_NFKC_FAILED: The Unicode NFKC operation failed. This
* usually indicate an internal error in the library.
* @STRINGPREP_MALLOC_ERROR: The malloc() was out of memory. This is
* usually a fatal error.
*
* Enumerated return codes of stringprep(), stringprep_profile()
* functions (and macros using those functions). The value 0 is
* guaranteed to always correspond to success.
*/
/**
* Stringprep_profile_flags:
* @STRINGPREP_NO_NFKC: Disable the NFKC normalization, as well as
* selecting the non-NFKC case folding tables. Usually the profile
* specifies BIDI and NFKC settings, and applications should not
* override it unless in special situations.
* @STRINGPREP_NO_BIDI: Disable the BIDI step. Usually the profile
* specifies BIDI and NFKC settings, and applications should not
* override it unless in special situations.
* @STRINGPREP_NO_UNASSIGNED: Make the library return with an error if
* string contains unassigned characters according to profile.
*
* Stringprep profile flags.
*/
/**
* Stringprep_profile_steps:
*
* Various steps in the stringprep algorithm. You really want to
* study the source code to understand this one. Only useful if you
* want to add another profile.
*/
/**
* stringprep_nameprep:
* @in: input/ouput array with string to prepare.
* @maxlen: maximum length of input/output array.
*
* Prepare the input UTF-8 string according to the nameprep profile.
* The AllowUnassigned flag is true, use
* stringprep_nameprep_no_unassigned() if you want a false
* AllowUnassigned. Returns 0 iff successful, or an error code.
**/
/**
* stringprep_nameprep_no_unassigned:
* @in: input/ouput array with string to prepare.
* @maxlen: maximum length of input/output array.
*
* Prepare the input UTF-8 string according to the nameprep profile.
* The AllowUnassigned flag is false, use stringprep_nameprep() for
* true AllowUnassigned. Returns 0 iff successful, or an error code.
**/
/**
* stringprep_iscsi:
* @in: input/ouput array with string to prepare.
* @maxlen: maximum length of input/output array.
*
* Prepare the input UTF-8 string according to the draft iSCSI
* stringprep profile. Returns 0 iff successful, or an error code.
**/
/**
* stringprep_plain:
* @in: input/ouput array with string to prepare.
* @maxlen: maximum length of input/output array.
*
* Prepare the input UTF-8 string according to the draft SASL
* ANONYMOUS profile. Returns 0 iff successful, or an error code.
**/
/**
* stringprep_xmpp_nodeprep:
* @in: input/ouput array with string to prepare.
* @maxlen: maximum length of input/output array.
*
* Prepare the input UTF-8 string according to the draft XMPP node
* identifier profile. Returns 0 iff successful, or an error code.
**/
/**
* stringprep_xmpp_resourceprep:
* @in: input/ouput array with string to prepare.
* @maxlen: maximum length of input/output array.
*
* Prepare the input UTF-8 string according to the draft XMPP resource
* identifier profile. Returns 0 iff successful, or an error code.
**/

View File

@ -1,209 +0,0 @@
/* stringprep.h Header file for stringprep functions. -*- c -*-
* Copyright (C) 2002, 2003, 2004 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _STRINGPREP_H
#define _STRINGPREP_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h> /* size_t */
#include <unistd.h> /* ssize_t */
#include <stdint.h> /* uint32_t */
#define STRINGPREP_VERSION "0.4.3"
/* Error codes. */
typedef enum
{
STRINGPREP_OK = 0,
/* Stringprep errors. */
STRINGPREP_CONTAINS_UNASSIGNED = 1,
STRINGPREP_CONTAINS_PROHIBITED = 2,
STRINGPREP_BIDI_BOTH_L_AND_RAL = 3,
STRINGPREP_BIDI_LEADTRAIL_NOT_RAL = 4,
STRINGPREP_BIDI_CONTAINS_PROHIBITED = 5,
/* Error in calling application. */
STRINGPREP_TOO_SMALL_BUFFER = 100,
STRINGPREP_PROFILE_ERROR = 101,
STRINGPREP_FLAG_ERROR = 102,
STRINGPREP_UNKNOWN_PROFILE = 103,
/* Internal errors. */
STRINGPREP_NFKC_FAILED = 200,
STRINGPREP_MALLOC_ERROR = 201
} Stringprep_rc;
/* Flags used when calling stringprep(). */
typedef enum
{
STRINGPREP_NO_NFKC = 1,
STRINGPREP_NO_BIDI = 2,
STRINGPREP_NO_UNASSIGNED = 4
} Stringprep_profile_flags;
/* Steps in a stringprep profile. */
typedef enum
{
STRINGPREP_NFKC = 1,
STRINGPREP_BIDI = 2,
STRINGPREP_MAP_TABLE = 3,
STRINGPREP_UNASSIGNED_TABLE = 4,
STRINGPREP_PROHIBIT_TABLE = 5,
STRINGPREP_BIDI_PROHIBIT_TABLE = 6,
STRINGPREP_BIDI_RAL_TABLE = 7,
STRINGPREP_BIDI_L_TABLE = 8
} Stringprep_profile_steps;
#define STRINGPREP_MAX_MAP_CHARS 4
struct Stringprep_table_element
{
uint32_t start;
uint32_t end; /* 0 if only one character */
uint32_t map[STRINGPREP_MAX_MAP_CHARS]; /* NULL if end is not 0 */
};
typedef struct Stringprep_table_element Stringprep_table_element;
struct Stringprep_table
{
Stringprep_profile_steps operation;
Stringprep_profile_flags flags;
const Stringprep_table_element *table;
};
typedef struct Stringprep_table Stringprep_profile;
struct Stringprep_profiles
{
const char *name;
const Stringprep_profile *tables;
};
typedef struct Stringprep_profiles Stringprep_profiles;
extern const Stringprep_profiles stringprep_profiles[];
/* Profiles */
extern const Stringprep_table_element stringprep_rfc3454_A_1[];
extern const Stringprep_table_element stringprep_rfc3454_B_1[];
extern const Stringprep_table_element stringprep_rfc3454_B_2[];
extern const Stringprep_table_element stringprep_rfc3454_B_3[];
extern const Stringprep_table_element stringprep_rfc3454_C_1_1[];
extern const Stringprep_table_element stringprep_rfc3454_C_1_2[];
extern const Stringprep_table_element stringprep_rfc3454_C_2_1[];
extern const Stringprep_table_element stringprep_rfc3454_C_2_2[];
extern const Stringprep_table_element stringprep_rfc3454_C_3[];
extern const Stringprep_table_element stringprep_rfc3454_C_4[];
extern const Stringprep_table_element stringprep_rfc3454_C_5[];
extern const Stringprep_table_element stringprep_rfc3454_C_6[];
extern const Stringprep_table_element stringprep_rfc3454_C_7[];
extern const Stringprep_table_element stringprep_rfc3454_C_8[];
extern const Stringprep_table_element stringprep_rfc3454_C_9[];
extern const Stringprep_table_element stringprep_rfc3454_D_1[];
extern const Stringprep_table_element stringprep_rfc3454_D_2[];
/* Nameprep */
extern const Stringprep_profile stringprep_nameprep[];
#define stringprep_nameprep(in, maxlen) \
stringprep(in, maxlen, 0, stringprep_nameprep)
#define stringprep_nameprep_no_unassigned(in, maxlen) \
stringprep(in, maxlen, STRINGPREP_NO_UNASSIGNED, stringprep_nameprep)
/* SASL */
extern const Stringprep_profile stringprep_saslprep[];
extern const Stringprep_profile stringprep_plain[];
extern const Stringprep_profile stringprep_trace[];
#define stringprep_plain(in, maxlen) \
stringprep(in, maxlen, 0, stringprep_plain)
/* Kerberos */
extern const Stringprep_profile stringprep_kerberos5[];
#define stringprep_kerberos5(in, maxlen) \
stringprep(in, maxlen, 0, stringprep_kerberos5)
/* XMPP */
extern const Stringprep_profile stringprep_xmpp_nodeprep[];
extern const Stringprep_profile stringprep_xmpp_resourceprep[];
extern const Stringprep_table_element stringprep_xmpp_nodeprep_prohibit[];
#define stringprep_xmpp_nodeprep(in, maxlen) \
stringprep(in, maxlen, 0, stringprep_xmpp_nodeprep)
#define stringprep_xmpp_resourceprep(in, maxlen) \
stringprep(in, maxlen, 0, stringprep_xmpp_resourceprep)
/* iSCSI */
extern const Stringprep_profile stringprep_iscsi[];
#define stringprep_iscsi(in, maxlen) \
stringprep(in, maxlen, 0, stringprep_iscsi)
/* API */
extern int stringprep_4i (uint32_t * ucs4, size_t * len, size_t maxucs4len,
Stringprep_profile_flags flags,
const Stringprep_profile * profile);
extern int stringprep_4zi (uint32_t * ucs4, size_t maxucs4len,
Stringprep_profile_flags flags,
const Stringprep_profile * profile);
extern int stringprep (char *in, size_t maxlen,
Stringprep_profile_flags flags,
const Stringprep_profile * profile);
extern int stringprep_profile (const char *in,
char **out,
const char *profile,
Stringprep_profile_flags flags);
extern const char *stringprep_check_version (const char *req_version);
/* Utility */
extern int stringprep_unichar_to_utf8 (uint32_t c, char *outbuf);
extern uint32_t stringprep_utf8_to_unichar (const char *p);
extern uint32_t *stringprep_utf8_to_ucs4 (const char *str, ssize_t len,
size_t * items_written);
extern char *stringprep_ucs4_to_utf8 (const uint32_t * str, ssize_t len,
size_t * items_read,
size_t * items_written);
extern char *stringprep_utf8_nfkc_normalize (const char *str, ssize_t len);
extern uint32_t *stringprep_ucs4_nfkc_normalize (uint32_t * str,
ssize_t len);
extern const char *stringprep_locale_charset (void);
extern char *stringprep_convert (const char *str,
const char *to_codeset,
const char *from_codeset);
extern char *stringprep_locale_to_utf8 (const char *str);
extern char *stringprep_utf8_to_locale (const char *str);
#ifdef __cplusplus
}
#endif
#endif /* _STRINGPREP_H */

View File

@ -1,150 +0,0 @@
/* toutf8.c --- Convert strings from system locale into UTF-8.
* Copyright (C) 2002, 2003, 2004, 2005 Simon Josefsson
*
* This file is part of GNU Libidn.
*
* GNU Libidn is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* GNU Libidn is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GNU Libidn; if not, see <http://www.gnu.org/licenses/>.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
/* Get prototypes. */
#include "stringprep.h"
/* Get fprintf. */
#include <stdio.h>
/* Get getenv. */
#include <stdlib.h>
/* Get strlen. */
#include <string.h>
/* Get iconv_string. */
#include "iconvme.h"
#ifdef _LIBC
# define HAVE_ICONV 1
# define LOCALE_WORKS 1
#endif
#if LOCALE_WORKS
# include <langinfo.h>
# include <locale.h>
#endif
#ifdef _LIBC
# define stringprep_locale_charset() nl_langinfo (CODESET)
#else
/**
* stringprep_locale_charset - return charset used in current locale
*
* Find out current locale charset. The function respect the CHARSET
* environment variable, but typically uses nl_langinfo(CODESET) when
* it is supported. It fall back on "ASCII" if CHARSET isn't set and
* nl_langinfo isn't supported or return anything.
*
* Note that this function return the application's locale's preferred
* charset (or thread's locale's preffered charset, if your system
* support thread-specific locales). It does not return what the
* system may be using. Thus, if you receive data from external
* sources you cannot in general use this function to guess what
* charset it is encoded in. Use stringprep_convert from the external
* representation into the charset returned by this function, to have
* data in the locale encoding.
*
* Return value: Return the character set used by the current locale.
* It will never return NULL, but use "ASCII" as a fallback.
**/
const char *
stringprep_locale_charset (void)
{
const char *charset = getenv ("CHARSET"); /* flawfinder: ignore */
if (charset && *charset)
return charset;
# ifdef LOCALE_WORKS
charset = nl_langinfo (CODESET);
if (charset && *charset)
return charset;
# endif
return "ASCII";
}
#endif
/**
* stringprep_convert - encode string using new character set
* @str: input zero-terminated string.
* @to_codeset: name of destination character set.
* @from_codeset: name of origin character set, as used by @str.
*
* Convert the string from one character set to another using the
* system's iconv() function.
*
* Return value: Returns newly allocated zero-terminated string which
* is @str transcoded into to_codeset.
**/
char *
stringprep_convert (const char *str,
const char *to_codeset, const char *from_codeset)
{
#if HAVE_ICONV
return iconv_string (str, from_codeset, to_codeset);
#else
char *p;
fprintf (stderr, "libidn: warning: libiconv not installed, cannot "
"convert data to UTF-8\n");
p = malloc (strlen (str) + 1);
if (!p)
return NULL;
return strcpy (p, str);
#endif
}
/**
* stringprep_locale_to_utf8 - convert locale encoded string to UTF-8
* @str: input zero terminated string.
*
* Convert string encoded in the locale's character set into UTF-8 by
* using stringprep_convert().
*
* Return value: Returns newly allocated zero-terminated string which
* is @str transcoded into UTF-8.
**/
char *
stringprep_locale_to_utf8 (const char *str)
{
return stringprep_convert (str, "UTF-8", stringprep_locale_charset ());
}
/**
* stringprep_utf8_to_locale - encode UTF-8 string to locale encoding
* @str: input zero terminated string.
*
* Convert string encoded in UTF-8 into the locale's character set by
* using stringprep_convert().
*
* Return value: Returns newly allocated zero-terminated string which
* is @str transcoded into the locale's character set.
**/
char *
stringprep_utf8_to_locale (const char *str)
{
return stringprep_convert (str, stringprep_locale_charset (), "UTF-8");
}

View File

@ -42,9 +42,6 @@
/* Support code. */
#include <check_pf.c>
#include <check_native.c>
#ifdef HAVE_LIBIDN
# include <libidn/idn-stub.c>
#endif
/* Some variables normally defined in libc. */
service_user *__nss_hosts_database attribute_hidden;

View File

@ -60,6 +60,9 @@ tests += \
# These tests need libdl.
ifeq (yes,$(build-shared))
tests += \
tst-resolv-ai_idn \
tst-resolv-ai_idn-latin1 \
tst-resolv-ai_idn-nolibidn2 \
tst-resolv-canonname \
# uses DEPRECATED_RES_USE_INET6 from <resolv-internal.h>.
@ -72,7 +75,13 @@ tests-internal += \
tst-resolv-res_ninit \
tst-resolv-threads \
endif
# Used by tst-resolv-ai_idn-nolibidn2 to disable libidn2 (by not
# providing any functions in libidn2.so.0).
modules-names += tst-no-libidn2
extra-test-objs += tst-no-libidn2.os
LDFLAGS-tst-no-libidn2.so = -Wl,-soname,libidn2.so.0
endif # $(build-shared)
# This test accesses __inet_ntop_length, an internal libc function.
tests-internal += tst-inet_pton
@ -128,6 +137,9 @@ generated += mtrace-tst-leaks.out tst-leaks.mtrace \
include ../Rules
LOCALES := en_US.UTF-8 en_US.ISO-8859-1
include ../gen-locales.mk
CFLAGS-res_hconf.c += -fexceptions
# The DNS NSS modules needs the resolver.
@ -159,6 +171,16 @@ $(objpfx)mtrace-tst-resolv-res_ninit.out: $(objpfx)tst-resolv-res_ninit.out
$(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-ai_idn: \
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-ai_idn-latin1: \
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-ai_idn-nolibidn2: \
$(libdl) $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-ai_idn.out: $(gen-locales)
$(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales)
$(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
$(gen-locales) $(objpfx)tst-no-libidn2.so
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)

View File

@ -605,10 +605,10 @@ struct gaicb
in the current locale's character set)
before looking it up. */
# define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */
# define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode
code points. */
# define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to
STD3 rules. */
# define AI_IDN_ALLOW_UNASSIGNED \
__glibc_macro_warning ("AI_IDN_ALLOW_UNASSIGNED is deprecated") 0x0100
# define AI_IDN_USE_STD3_ASCII_RULES \
__glibc_macro_warning ("AI_IDN_USE_STD3_ASCII_RULES is deprecated") 0x0200
# endif
# define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */
@ -646,10 +646,10 @@ struct gaicb
# define NI_DGRAM 16 /* Look up UDP service rather than TCP. */
# ifdef __USE_GNU
# define NI_IDN 32 /* Convert name from IDN format. */
# define NI_IDN_ALLOW_UNASSIGNED 64 /* Don't reject unassigned Unicode
code points. */
# define NI_IDN_USE_STD3_ASCII_RULES 128 /* Validate strings according to
STD3 rules. */
# define NI_IDN_ALLOW_UNASSIGNED \
__glibc_macro_warning ("NI_IDN_ALLOW_UNASSIGNED is deprecated") 64
# define NI_IDN_USE_STD3_ASCII_RULES \
__glibc_macro_warning ("NI_IDN_USE_STD3_ASCII_RULES is deprecated") 128
# endif
/* Translate name of a service location and/or a service name to set of

2
resolv/tst-no-libidn2.c Normal file
View File

@ -0,0 +1,2 @@
/* Compiled into an empty shared object. Used by
tst-resolv-ai_idn-nolibidn2 to disable libidn2. */

View File

@ -0,0 +1,569 @@
/* Common code for AI_IDN/NI_IDN tests.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Before including this file, TEST_USE_UTF8 must be defined to 1 or
0, depending on whether a UTF-8 locale is used or a Latin-1
locale. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/check_nss.h>
#include <support/resolv_test.h>
#include <support/support.h>
/* Name of the shared object for libidn2. */
#define LIBIDN2_SONAME "libidn2.so.0"
#if TEST_USE_UTF8
/* UTF-8 encoding of "nämchen" (German for “namelet”). */
# define NAEMCHEN "n\xC3\xA4mchen"
/* UTF-8 encoding of "שם" (Hebrew for “name”). */
# define SHEM "\xD7\xA9\xD7\x9D"
/* UTF-8 encoding of "buße" (German for “penance”). This used to be
encoded as "busse" (busses) in IDNA2003. */
# define BUSSE "bu\xC3\x9F""e"
#else
/* Latin-1 encodings, as far as they are available. */
# define NAEMCHEN "n\xE4mchen"
# define BUSSE "bu\xDF""e"
#endif
/* IDNA encoding of NAEMCHEN. */
#define NAEMCHEN_IDNA "xn--nmchen-bua"
/* IDNA encoding of NAEMCHEN "_zwo". */
#define NAEMCHEN_ZWO_IDNA "xn--nmchen_zwo-q5a"
/* IDNA encoding of SHEM. */
#define SHEM_IDNA "xn--iebx"
/* IDNA encoding of BUSSE. */
#define BUSSE_IDNA "xn--bue-6ka"
/* IDNA encoding of "שם1". */
#define SHEM1_IDNA "xn--1-qic9a"
/* Another IDNA name. */
#define ANDERES_NAEMCHEN "anderes-" NAEMCHEN
#define ANDERES_NAEMCHEN_IDNA "xn--anderes-nmchen-eib"
/* Controls the kind of test data in a PTR lookup response. */
enum gni_test
{
gni_non_idn_name,
gni_non_idn_cname_to_non_idn_name,
gni_non_idn_cname_to_idn_name,
gni_idn_name,
gni_idn_shem,
gni_idn_shem1,
gni_idn_cname_to_non_idn_name,
gni_idn_cname_to_idn_name,
gni_invalid_idn_1,
gni_invalid_idn_2,
};
/* Called from response below. The LSB (first byte) controls what
goes into the response, see enum gni_test. */
static void
response_ptr (const struct resolv_response_context *ctx,
struct resolv_response_builder *b, const char *qname)
{
int comp[4] = { 0 };
TEST_COMPARE (sscanf (qname, "%d.%d.%d.%d.in-addr.arpa",
&comp[0], &comp[1], &comp[2], &comp[3]), 4);
const char *next_name;
switch ((enum gni_test) comp[0])
{
/* First name in response is non-IDN name. */
case gni_non_idn_name:
resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
resolv_response_add_name (b, "non-idn.example");
resolv_response_close_record (b);
return;
case gni_non_idn_cname_to_non_idn_name:
resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
next_name = "non-idn-cname.example";
resolv_response_add_name (b, next_name);
resolv_response_close_record (b);
resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
resolv_response_add_name (b, "non-idn-name.example");
resolv_response_close_record (b);
return;
case gni_non_idn_cname_to_idn_name:
resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
next_name = "non-idn-cname.example";
resolv_response_add_name (b, next_name);
resolv_response_close_record (b);
resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
resolv_response_add_name (b, NAEMCHEN_IDNA ".example");
resolv_response_close_record (b);
return;
/* First name in response is IDN name. */
case gni_idn_name:
resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
resolv_response_add_name (b, "xn--nmchen-bua.example");
resolv_response_close_record (b);
return;
case gni_idn_shem:
resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
resolv_response_add_name (b, SHEM_IDNA ".example");
resolv_response_close_record (b);
return;
case gni_idn_shem1:
resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
resolv_response_add_name (b, SHEM1_IDNA ".example");
resolv_response_close_record (b);
return;
case gni_idn_cname_to_non_idn_name:
resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
next_name = NAEMCHEN_IDNA ".example";
resolv_response_add_name (b, next_name);
resolv_response_close_record (b);
resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
resolv_response_add_name (b, "non-idn-name.example");
resolv_response_close_record (b);
return;
case gni_idn_cname_to_idn_name:
resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
next_name = NAEMCHEN_IDNA ".example";
resolv_response_add_name (b, next_name);
resolv_response_close_record (b);
resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
resolv_response_add_name (b, ANDERES_NAEMCHEN_IDNA ".example");
resolv_response_close_record (b);
return;
/* Invalid IDN encodings. */
case gni_invalid_idn_1:
resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
resolv_response_add_name (b, "xn---.example");
resolv_response_close_record (b);
return;
case gni_invalid_idn_2:
resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
resolv_response_add_name (b, "xn--x.example");
resolv_response_close_record (b);
return;
}
FAIL_EXIT1 ("invalid PTR query: %s", qname);
}
/* For PTR responses, see above. A/AAAA queries can request
additional CNAMEs in the response by include ".cname." and
".idn-cname." in the query. The LSB in the address contains the
first byte of the QNAME. */
static void
response (const struct resolv_response_context *ctx,
struct resolv_response_builder *b,
const char *qname, uint16_t qclass, uint16_t qtype)
{
TEST_VERIFY_EXIT (qclass == C_IN);
for (const char *p = qname; *p != '\0'; ++p)
if (!(('0' <= *p && *p <= '9')
|| ('a' <= *p && *p <= 'z')
|| ('A' <= *p && *p <= 'Z')
|| *p == '.' || *p == '-' || *p == '_'))
{
/* Non-ASCII query. Reply with NXDOMAIN. */
struct resolv_response_flags flags = { .rcode = 3 };
resolv_response_init (b, flags);
resolv_response_add_question (b, qname, qclass, qtype);
return;
}
struct resolv_response_flags flags = { 0 };
resolv_response_init (b, flags);
resolv_response_add_question (b, qname, qclass, qtype);
resolv_response_section (b, ns_s_an);
if (qtype == T_PTR)
{
response_ptr (ctx, b, qname);
return;
}
bool with_cname = strstr (qname, ".cname.") != NULL;
bool with_idn_cname = strstr (qname, ".idn-cname.") != NULL;
const char *next_name = qname;
if (with_cname)
{
next_name = "non-idn-cname.example";
resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
resolv_response_add_name (b, next_name);
resolv_response_close_record (b);
}
if (with_idn_cname)
{
next_name = ANDERES_NAEMCHEN_IDNA ".example";
resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
resolv_response_add_name (b, next_name);
resolv_response_close_record (b);
}
resolv_response_open_record (b, next_name, C_IN, qtype, 0);
switch (qtype)
{
case T_A:
{
char addr[4] = { 192, 0, 2, qname[0] };
resolv_response_add_data (b, &addr, sizeof (addr));
}
break;
case T_AAAA:
{
char addr[16]
= { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
qname[0] };
resolv_response_add_data (b, &addr, sizeof (addr));
}
default:
FAIL_EXIT1 ("invalid qtype: %d", qtype);
}
resolv_response_close_record (b);
}
/* Check the result of a getaddrinfo call. */
static void
check_ai (const char *name, int ai_flags, const char *expected)
{
struct addrinfo hints =
{
.ai_flags = ai_flags,
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
struct addrinfo *ai;
char *query = xasprintf ("%s:80 AF_INET/0x%x", name, ai_flags);
int ret = getaddrinfo (name, "80", &hints, &ai);
check_addrinfo (query, ai, ret, expected);
if (ret == 0)
freeaddrinfo (ai);
free (query);
}
/* Run one getnameinfo test. FLAGS is automatically augmented with
NI_NUMERICSERV. */
static void
gni_test (enum gni_test code, unsigned int flags, const char *expected)
{
struct sockaddr_in sin =
{
.sin_family = AF_INET,
.sin_port = htons (80),
.sin_addr = { htonl (0xc0000200 | code) }, /* 192.0.2.0/24 network. */
};
char host[1024];
char service[1024];
int ret = getnameinfo ((const struct sockaddr *) &sin, sizeof (sin),
host, sizeof (host), service, sizeof (service),
flags| NI_NUMERICSERV);
if (ret != 0)
{
if (expected == NULL)
TEST_COMPARE (ret, EAI_IDN_ENCODE);
else
{
support_record_failure ();
printf ("error: getnameinfo failed (code %d, flags 0x%x): %s (%d)\n",
(int) code, flags, gai_strerror (ret), ret);
}
}
else if (ret == 0 && expected == NULL)
{
support_record_failure ();
printf ("error: getnameinfo unexpected success (code %d, flags 0x%x)\n",
(int) code, flags);
}
else if (strcmp (host, expected) != 0 || strcmp (service, "80") != 0)
{
support_record_failure ();
printf ("error: getnameinfo test failure (code %d, flags 0x%x)\n"
" expected host: \"%s\"\n"
" expected service: \"80\"\n"
" actual host: \"%s\"\n"
" actual service: \"%s\"\n",
(int) code, flags, expected, host, service);
}
}
/* Tests for getaddrinfo which assume a working libidn2 library. */
__attribute__ ((unused))
static void
gai_tests_with_libidn2 (void)
{
/* No CNAME. */
check_ai ("non-idn.example", 0,
"address: STREAM/TCP 192.0.2.110 80\n");
check_ai ("non-idn.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.110 80\n");
check_ai ("non-idn.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: non-idn.example\n"
"address: STREAM/TCP 192.0.2.110 80\n");
check_ai (NAEMCHEN ".example", 0,
"error: Name or service not known\n");
check_ai (NAEMCHEN ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (NAEMCHEN ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " NAEMCHEN ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
#if TEST_USE_UTF8
check_ai (SHEM ".example", 0,
"error: Name or service not known\n");
check_ai (SHEM ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " SHEM ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM ".example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " SHEM_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM "1.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " SHEM "1.example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " SHEM1_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
#endif
/* Check that non-transitional mode is active. German sharp S
should not turn into SS. */
check_ai (BUSSE ".example", 0,
"error: Name or service not known\n");
check_ai (BUSSE ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " BUSSE_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " BUSSE ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
/* Check that Unicode TR 46 mode is active. Underscores should be
permitted in IDNA components. */
check_ai (NAEMCHEN "_zwo.example", 0,
"error: Name or service not known\n");
check_ai (NAEMCHEN "_zwo.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " NAEMCHEN_ZWO_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " NAEMCHEN "_zwo.example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
/* No CNAME, but already IDN-encoded. */
check_ai (NAEMCHEN_IDNA ".example", 0,
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (NAEMCHEN_IDNA ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " NAEMCHEN ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM_IDNA ".example", 0,
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM_IDNA ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.120 80\n");
check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " SHEM_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
#if TEST_USE_UTF8
check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " SHEM ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
#else
check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " SHEM_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
#endif
/* Invalid IDNA canonical name is returned as-is. */
check_ai ("xn---.example", AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_CANONIDN\n"
"canonname: xn---.example\n"
"address: STREAM/TCP 192.0.2.120 80\n");
/* Non-IDN CNAME. */
check_ai ("with.cname.example", 0,
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("with.cname.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("with.cname.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: non-idn-cname.example\n"
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("with.cname." NAEMCHEN ".example", 0,
"error: Name or service not known\n");
check_ai ("with.cname." NAEMCHEN ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("with.cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: non-idn-cname.example\n"
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("with.cname." NAEMCHEN ".example",
AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: non-idn-cname.example\n"
"address: STREAM/TCP 192.0.2.119 80\n");
/* IDN CNAME. */
check_ai ("With.idn-cname.example", 0,
"address: STREAM/TCP 192.0.2.87 80\n");
check_ai ("With.idn-cname.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.87 80\n");
check_ai ("With.idn-cname.example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.87 80\n");
check_ai ("With.idn-cname.example",
AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " ANDERES_NAEMCHEN ".example\n"
"address: STREAM/TCP 192.0.2.87 80\n");
check_ai ("With.idn-cname." NAEMCHEN ".example", 0,
"error: Name or service not known\n");
check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("With.idn-cname." NAEMCHEN ".example",
AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " ANDERES_NAEMCHEN ".example\n"
"address: STREAM/TCP 192.0.2.119 80\n");
/* Non-IDN to IDN CNAME chain. */
check_ai ("both.cname.idn-cname.example", 0,
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname.example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname.example",
AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " ANDERES_NAEMCHEN ".example\n"
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname." NAEMCHEN ".example", 0,
"error: Name or service not known\n");
check_ai ("both.cname.idn-cname." NAEMCHEN ".example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname." NAEMCHEN ".example",
AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname." NAEMCHEN ".example",
AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " ANDERES_NAEMCHEN ".example\n"
"address: STREAM/TCP 192.0.2.98 80\n");
}
/* Tests for getnameinfo which assume a working libidn2 library. */
__attribute__ ((unused))
static void
gni_tests_with_libidn2 (void)
{
gni_test (gni_non_idn_name, 0, "non-idn.example");
gni_test (gni_non_idn_name, NI_IDN, "non-idn.example");
gni_test (gni_non_idn_name, NI_NUMERICHOST, "192.0.2.0");
gni_test (gni_non_idn_name, NI_NUMERICHOST | NI_IDN, "192.0.2.0");
gni_test (gni_non_idn_cname_to_non_idn_name, 0, "non-idn-name.example");
gni_test (gni_non_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example");
gni_test (gni_non_idn_cname_to_idn_name, 0, NAEMCHEN_IDNA ".example");
gni_test (gni_non_idn_cname_to_idn_name, NI_IDN, NAEMCHEN ".example");
gni_test (gni_idn_name, 0, NAEMCHEN_IDNA ".example");
gni_test (gni_idn_name, NI_IDN, NAEMCHEN ".example");
gni_test (gni_idn_shem, 0, SHEM_IDNA ".example");
gni_test (gni_idn_shem1, 0, SHEM1_IDNA ".example");
#if TEST_USE_UTF8
gni_test (gni_idn_shem, NI_IDN, SHEM ".example");
gni_test (gni_idn_shem1, NI_IDN, SHEM "1.example");
#else
gni_test (gni_idn_shem, NI_IDN, SHEM_IDNA ".example");
gni_test (gni_idn_shem1, NI_IDN, SHEM1_IDNA ".example");
#endif
gni_test (gni_idn_cname_to_non_idn_name, 0, "non-idn-name.example");
gni_test (gni_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example");
gni_test (gni_idn_cname_to_idn_name, 0, ANDERES_NAEMCHEN_IDNA ".example");
gni_test (gni_idn_cname_to_idn_name, NI_IDN, ANDERES_NAEMCHEN ".example");
/* Test encoding errors. */
gni_test (gni_invalid_idn_1, 0, "xn---.example");
gni_test (gni_invalid_idn_1, NI_IDN, "xn---.example");
gni_test (gni_invalid_idn_2, 0, "xn--x.example");
gni_test (gni_invalid_idn_2, NI_IDN, "xn--x.example");
}

View File

@ -0,0 +1,50 @@
/* Test getaddrinfo and getnameinfo with AI_IDN, NI_IDN (Latin-1).
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define TEST_USE_UTF8 0
#include "tst-resolv-ai_idn-common.c"
#include <locale.h>
#include <support/xdlfcn.h>
static int
do_test (void)
{
void *handle = dlopen (LIBIDN2_SONAME, RTLD_LAZY);
if (handle == NULL)
FAIL_UNSUPPORTED ("libidn2 not installed");
if (setlocale (LC_CTYPE, "en_US.ISO-8859-1") == NULL)
FAIL_EXIT1 ("setlocale: %m");
struct resolv_test *aux = resolv_test_start
((struct resolv_redirect_config)
{
.response_callback = response,
});
gai_tests_with_libidn2 ();
gni_tests_with_libidn2 ();
resolv_test_end (aux);
xdlclose (handle);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,151 @@
/* Test getaddrinfo and getnameinfo without usable libidn2.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define TEST_USE_UTF8 1
#include "tst-resolv-ai_idn-common.c"
#include <locale.h>
#include <support/xdlfcn.h>
/* Tests for getaddrinfo. */
static void
gai_tests (void)
{
/* No CNAME. */
check_ai ("non-idn.example", 0,
"address: STREAM/TCP 192.0.2.110 80\n");
check_ai ("non-idn.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.110 80\n");
check_ai ("non-idn.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: non-idn.example\n"
"address: STREAM/TCP 192.0.2.110 80\n");
/* This gets passed over the network to the server, so it will
result in an NXDOMAIN error. */
check_ai (NAEMCHEN ".example", 0,
"error: Name or service not known\n");
/* Due to missing libidn2, this fails inside getaddrinfo. */
check_ai (NAEMCHEN ".example", AI_IDN,
"error: Parameter string not correctly encoded\n");
check_ai (NAEMCHEN ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"error: Parameter string not correctly encoded\n");
/* Non-IDN CNAME. */
check_ai ("with.cname.example", 0,
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("with.cname.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.119 80\n");
check_ai ("with.cname.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: non-idn-cname.example\n"
"address: STREAM/TCP 192.0.2.119 80\n");
/* IDN CNAME. */
check_ai ("With.idn-cname.example", 0,
"address: STREAM/TCP 192.0.2.87 80\n");
check_ai ("With.idn-cname.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.87 80\n");
check_ai ("With.idn-cname.example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.87 80\n");
check_ai ("With.idn-cname.example",
AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.87 80\n");
/* Non-IDN to IDN CNAME chain. */
check_ai ("both.cname.idn-cname.example", 0,
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname.example", AI_IDN,
"flags: AI_IDN\n"
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname.example", AI_IDN | AI_CANONNAME,
"flags: AI_CANONNAME AI_IDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.98 80\n");
check_ai ("both.cname.idn-cname.example",
AI_IDN | AI_CANONNAME | AI_CANONIDN,
"flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
"canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
"address: STREAM/TCP 192.0.2.98 80\n");
}
/* Tests for getnameinfo. */
static void
gni_tests (void)
{
/* All non-IDN an IDN results are the same due to lack of libidn2
support. */
for (int do_ni_idn = 0; do_ni_idn < 2; ++do_ni_idn)
{
int flags = 0;
if (do_ni_idn)
flags |= NI_IDN;
gni_test (gni_non_idn_name, flags, "non-idn.example");
gni_test (gni_non_idn_name, flags | NI_NUMERICHOST, "192.0.2.0");
gni_test (gni_non_idn_cname_to_non_idn_name, flags,
"non-idn-name.example");
gni_test (gni_non_idn_cname_to_idn_name, flags,
NAEMCHEN_IDNA ".example");
gni_test (gni_idn_name, flags, NAEMCHEN_IDNA ".example");
gni_test (gni_idn_cname_to_non_idn_name, flags, "non-idn-name.example");
gni_test (gni_idn_cname_to_idn_name, flags,
ANDERES_NAEMCHEN_IDNA ".example");
/* Test encoding errors. */
gni_test (gni_invalid_idn_1, flags, "xn---.example");
gni_test (gni_invalid_idn_2, flags, "xn--x.example");
}
}
static int
do_test (void)
{
void *handle = xdlopen ("tst-no-libidn2.so", RTLD_LAZY);
{
/* Verify that this replaced libidn2. */
void *handle2 = xdlopen (LIBIDN2_SONAME, RTLD_LAZY | RTLD_NOLOAD);
TEST_VERIFY (handle2 == handle);
xdlclose (handle2);
}
if (setlocale (LC_CTYPE, "en_US.UTF-8") == NULL)
FAIL_EXIT1 ("setlocale: %m");
struct resolv_test *aux = resolv_test_start
((struct resolv_redirect_config)
{
.response_callback = response,
});
gai_tests ();
gni_tests ();
resolv_test_end (aux);
xdlclose (handle);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,49 @@
/* Test getaddrinfo and getnameinfo with AI_IDN, NI_IDN (UTF-8).
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define TEST_USE_UTF8 1
#include "tst-resolv-ai_idn-common.c"
#include <locale.h>
#include <support/xdlfcn.h>
static int
do_test (void)
{
void *handle = dlopen (LIBIDN2_SONAME, RTLD_LAZY);
if (handle == NULL)
FAIL_UNSUPPORTED ("libidn2 not installed");
if (setlocale (LC_CTYPE, "en_US.UTF-8") == NULL)
FAIL_EXIT1 ("setlocale: %m");
struct resolv_test *aux = resolv_test_start
((struct resolv_redirect_config)
{
.response_callback = response,
});
gai_tests_with_libidn2 ();
gni_tests_with_libidn2 ();
resolv_test_end (aux);
xdlclose (handle);
return 0;
}
#include <support/test-driver.c>

View File

@ -67,8 +67,6 @@ format_ai_flags (FILE *out, struct addrinfo *ai)
FLAG (AI_ADDRCONFIG);
FLAG (AI_IDN);
FLAG (AI_CANONIDN);
FLAG (AI_IDN_ALLOW_UNASSIGNED);
FLAG (AI_IDN_USE_STD3_ASCII_RULES);
FLAG (AI_NUMERICSERV);
#undef FLAG
int remaining = ai->ai_flags & ~flags_printed;

View File

@ -85,9 +85,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <scratch_buffer.h>
#include <inet/net-internal.h>
#ifdef HAVE_LIBIDN
# include <idna.h>
#endif
/* Former AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES
flags, now ignored. */
#define DEPRECATED_AI_IDN 0x300
#if IS_IN (libc)
# define feof_unlocked(fp) __feof_unlocked (fp)
@ -478,35 +478,15 @@ gaih_inet (const char *name, const struct gaih_service *service,
at->scopeid = 0;
at->next = NULL;
#ifdef HAVE_LIBIDN
if (req->ai_flags & AI_IDN)
{
int idn_flags = 0;
if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
idn_flags |= IDNA_ALLOW_UNASSIGNED;
if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
idn_flags |= IDNA_USE_STD3_ASCII_RULES;
char *p = NULL;
int rc = __idna_to_ascii_lz (name, &p, idn_flags);
if (rc != IDNA_SUCCESS)
{
/* No need to jump to free_and_return here. */
if (rc == IDNA_MALLOC_ERROR)
return -EAI_MEMORY;
if (rc == IDNA_DLOPEN_ERROR)
return -EAI_SYSTEM;
return -EAI_IDN_ENCODE;
}
/* In case the output string is the same as the input string
no new string has been allocated. */
if (p != name)
{
name = p;
char *out;
result = __idna_to_dns_encoding (name, &out);
if (result != 0)
return -result;
name = out;
malloc_name = true;
}
}
#endif
if (__inet_aton (name, (struct in_addr *) at->addr) != 0)
{
@ -1032,40 +1012,24 @@ gaih_inet (const char *name, const struct gaih_service *service,
the passed in string. */
canon = orig_name;
#ifdef HAVE_LIBIDN
if (req->ai_flags & AI_CANONIDN)
bool do_idn = req->ai_flags & AI_CANONIDN;
if (do_idn)
{
int idn_flags = 0;
if (req->ai_flags & AI_IDN_ALLOW_UNASSIGNED)
idn_flags |= IDNA_ALLOW_UNASSIGNED;
if (req->ai_flags & AI_IDN_USE_STD3_ASCII_RULES)
idn_flags |= IDNA_USE_STD3_ASCII_RULES;
char *out;
int rc = __idna_to_unicode_lzlz (canon, &out, idn_flags);
if (rc != IDNA_SUCCESS)
{
if (rc == IDNA_MALLOC_ERROR)
result = -EAI_MEMORY;
else if (rc == IDNA_DLOPEN_ERROR)
result = -EAI_SYSTEM;
int rc = __idna_from_dns_encoding (canon, &out);
if (rc == 0)
canon = out;
else if (rc == EAI_IDN_ENCODE)
/* Use the punycode name as a fallback. */
do_idn = false;
else
result = -EAI_IDN_ENCODE;
{
result = -rc;
goto free_and_return;
}
/* In case the output string is the same as the input
string no new string has been allocated and we
make a copy. */
if (out == canon)
goto make_copy;
canon = out;
}
else
#endif
if (!do_idn)
{
#ifdef HAVE_LIBIDN
make_copy:
#endif
if (canonbuf != NULL)
/* We already allocated the string using malloc, but
the buffer is now owned by canon. */
@ -2226,10 +2190,7 @@ getaddrinfo (const char *name, const char *service,
if (hints->ai_flags
& ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST|AI_ADDRCONFIG|AI_V4MAPPED
#ifdef HAVE_LIBIDN
|AI_IDN|AI_CANONIDN|AI_IDN_ALLOW_UNASSIGNED
|AI_IDN_USE_STD3_ASCII_RULES
#endif
|AI_IDN|AI_CANONIDN|DEPRECATED_AI_IDN
|AI_NUMERICSERV|AI_ALL))
return EAI_BADFLAGS;

View File

@ -6,4 +6,3 @@ nis
nscd
nss
streams
libidn

View File

@ -1,9 +0,0 @@
# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
if test "$shared" = yes; then :
# Get this defined in config.h for main source code to test.
$as_echo "#define HAVE_LIBIDN 1" >>confdefs.h
fi

View File

@ -1,7 +0,0 @@
dnl glibc configure fragment for sysdeps/unix/inet.
GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
AS_IF([test "$shared" = yes], [
# Get this defined in config.h for main source code to test.
AC_DEFINE([HAVE_LIBIDN])
])