mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 01:33:36 +08:00
This provides an implementation of the IDNA2008 standard and fixes CVE-2016-6261, CVE-2016-6263, CVE-2017-14062.
This commit is contained in:
parent
5f7b841d3a
commit
7f9f1ecb71
64
ChangeLog
64
ChangeLog
@ -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.
|
||||
|
69
LICENSES
69
LICENSES
@ -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
24
NEWS
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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)
|
||||
|
@ -88,5 +88,7 @@ libc {
|
||||
|
||||
# Used from nscd.
|
||||
__inet6_scopeid_pton;
|
||||
__idna_to_dns_encoding;
|
||||
__idna_from_dns_encoding;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
if (out != h->h_name)
|
||||
{
|
||||
h->h_name = strdupa (out);
|
||||
free (out);
|
||||
}
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
if (!do_idn)
|
||||
h_name = h->h_name;
|
||||
|
||||
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
182
inet/idna.c
Normal 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
75
inet/idna_name_classify.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
73
inet/tst-idna_name_classify.c
Normal file
73
inet/tst-idna_name_classify.c
Normal 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>
|
@ -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
|
@ -1,6 +0,0 @@
|
||||
libcidn {
|
||||
GLIBC_PRIVATE {
|
||||
idna_to_ascii_lz;
|
||||
idna_to_unicode_lzlz;
|
||||
}
|
||||
}
|
@ -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 }
|
||||
};
|
10362
libidn/gunidecomp.h
10362
libidn/gunidecomp.h
File diff suppressed because it is too large
Load Diff
171
libidn/iconvme.c
171
libidn/iconvme.c
@ -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;
|
||||
}
|
@ -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 */
|
@ -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
|
834
libidn/idna.c
834
libidn/idna.c
@ -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.
|
||||
*/
|
@ -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 */
|
1057
libidn/nfkc.c
1057
libidn/nfkc.c
File diff suppressed because it is too large
Load Diff
@ -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}
|
||||
};
|
@ -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.
|
||||
*/
|
@ -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 */
|
3544
libidn/rfc3454.c
3544
libidn/rfc3454.c
File diff suppressed because it is too large
Load Diff
@ -1 +0,0 @@
|
||||
libcidn=1
|
@ -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.
|
||||
**/
|
@ -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 */
|
150
libidn/toutf8.c
150
libidn/toutf8.c
@ -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");
|
||||
}
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
2
resolv/tst-no-libidn2.c
Normal file
@ -0,0 +1,2 @@
|
||||
/* Compiled into an empty shared object. Used by
|
||||
tst-resolv-ai_idn-nolibidn2 to disable libidn2. */
|
569
resolv/tst-resolv-ai_idn-common.c
Normal file
569
resolv/tst-resolv-ai_idn-common.c
Normal 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");
|
||||
}
|
50
resolv/tst-resolv-ai_idn-latin1.c
Normal file
50
resolv/tst-resolv-ai_idn-latin1.c
Normal 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>
|
151
resolv/tst-resolv-ai_idn-nolibidn2.c
Normal file
151
resolv/tst-resolv-ai_idn-nolibidn2.c
Normal 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>
|
49
resolv/tst-resolv-ai_idn.c
Normal file
49
resolv/tst-resolv-ai_idn.c
Normal 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>
|
@ -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;
|
||||
|
@ -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;
|
||||
malloc_name = true;
|
||||
}
|
||||
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)
|
||||
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
|
||||
{
|
||||
if (rc == IDNA_MALLOC_ERROR)
|
||||
result = -EAI_MEMORY;
|
||||
else if (rc == IDNA_DLOPEN_ERROR)
|
||||
result = -EAI_SYSTEM;
|
||||
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;
|
||||
|
||||
|
@ -6,4 +6,3 @@ nis
|
||||
nscd
|
||||
nss
|
||||
streams
|
||||
libidn
|
||||
|
9
sysdeps/unix/inet/configure
vendored
9
sysdeps/unix/inet/configure
vendored
@ -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
|
@ -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])
|
||||
])
|
Loading…
Reference in New Issue
Block a user