Merged silc_1_0_branch to trunk. silc.trunk.merged.silc.1.0.branch.4
authorPekka Riikonen <priikone@silcnet.org>
Sun, 17 Apr 2005 12:04:01 +0000 (12:04 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Sun, 17 Apr 2005 12:04:01 +0000 (12:04 +0000)
cvs -z3 update -j silc_trunk_merged_silc_1_0_branch_3 -j silc_1_0_branch

266 files changed:
CHANGES
CREDITS
INSTALL
Makefile.ad [moved from Makefile.am.pre with 68% similarity]
Makefile.defines.in [moved from Makefile.defines.pre with 78% similarity]
Makefile.defines_int.in [moved from Makefile.defines_int.pre with 81% similarity]
README.CVS
README.DIST [new file with mode: 0644]
TODO
acconfig.h.pre [deleted file]
apps/Makefile.ad [new file with mode: 0644]
apps/autodist/AUTHORS [new file with mode: 0644]
apps/autodist/COPYING [new file with mode: 0644]
apps/autodist/INSTALL [new file with mode: 0644]
apps/autodist/Makefile.am [new file with mode: 0644]
apps/autodist/README [new file with mode: 0644]
apps/autodist/autodist.conf [new file with mode: 0644]
apps/autodist/autodist.in [new file with mode: 0755]
apps/autodist/configure.ad [new file with mode: 0644]
apps/autodist/default [new file with mode: 0644]
apps/autodist/doc/Makefile.am [new file with mode: 0644]
apps/autodist/doc/autodist.texi [new file with mode: 0644]
apps/autodist/doc/fdl.texi [new file with mode: 0644]
apps/autodist/doc/mdate-sh [new file with mode: 0755]
apps/autodist/doc/texinfo.tex [new file with mode: 0644]
apps/autodist/makedist.in [new file with mode: 0755]
apps/autodist/tests/Makefile.am [new file with mode: 0644]
apps/autodist/tests/autodist1.test [new file with mode: 0755]
apps/autodist/tests/autodist2.test [new file with mode: 0755]
apps/irssi/autogen.sh
apps/irssi/configure.in
apps/irssi/default.theme
apps/irssi/docs/help/in/action.in
apps/irssi/docs/help/in/cumode.in
apps/irssi/docs/help/in/kill.in
apps/irssi/docs/help/in/listkeys.in [new file with mode: 0644]
apps/irssi/docs/help/in/mmsg.in [new file with mode: 0644]
apps/irssi/docs/help/in/msg.in
apps/irssi/docs/help/in/nick.in
apps/irssi/docs/help/in/notice.in
apps/irssi/docs/help/in/oper.in
apps/irssi/docs/help/in/ping.in
apps/irssi/docs/help/in/silcnet.in [new file with mode: 0644]
apps/irssi/docs/help/in/silcoper.in
apps/irssi/docs/help/in/umode.in
apps/irssi/docs/help/in/watch.in
apps/irssi/docs/help/in/whois.in
apps/irssi/docs/help/in/whowas.in
apps/irssi/docs/signals.txt
apps/irssi/scripts/Makefile.am
apps/irssi/scripts/mime-test.pl [deleted file]
apps/irssi/scripts/silc-mime.pl [new file with mode: 0644]
apps/irssi/silc.conf
apps/irssi/src/fe-common/silc/Makefile.am
apps/irssi/src/fe-common/silc/fe-common-silc.c
apps/irssi/src/fe-common/silc/fe-messages.c [deleted file]
apps/irssi/src/fe-common/silc/fe-silc-channels.c [moved from apps/irssi/src/fe-common/silc/fe-channels.c with 96% similarity]
apps/irssi/src/fe-common/silc/fe-silc-channels.h [new file with mode: 0644]
apps/irssi/src/fe-common/silc/fe-silc-messages.c [new file with mode: 0644]
apps/irssi/src/fe-common/silc/fe-silc-messages.h [new file with mode: 0644]
apps/irssi/src/fe-common/silc/fe-silc-queries.c [new file with mode: 0644]
apps/irssi/src/fe-common/silc/fe-silc-queries.h [new file with mode: 0644]
apps/irssi/src/fe-common/silc/fe-silcnet.c [new file with mode: 0644]
apps/irssi/src/fe-common/silc/fe-silcnet.h [new file with mode: 0644]
apps/irssi/src/fe-common/silc/module-formats.c
apps/irssi/src/fe-common/silc/module-formats.h
apps/irssi/src/perl/Makefile.am
apps/irssi/src/perl/silc/Channel.xs [new file with mode: 0644]
apps/irssi/src/perl/silc/Makefile.PL.in [new file with mode: 0644]
apps/irssi/src/perl/silc/Query.xs [new file with mode: 0644]
apps/irssi/src/perl/silc/Server.xs [new file with mode: 0644]
apps/irssi/src/perl/silc/Silc.pm [new file with mode: 0644]
apps/irssi/src/perl/silc/Silc.xs [new file with mode: 0644]
apps/irssi/src/perl/silc/module.h [new file with mode: 0644]
apps/irssi/src/perl/silc/typemap [new file with mode: 0644]
apps/irssi/src/silc/core/Makefile.am
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/client_ops.h
apps/irssi/src/silc/core/clientutil.c
apps/irssi/src/silc/core/silc-channels.c
apps/irssi/src/silc/core/silc-chatnets.c [new file with mode: 0644]
apps/irssi/src/silc/core/silc-chatnets.h [new file with mode: 0644]
apps/irssi/src/silc/core/silc-cmdqueue.c [new file with mode: 0644]
apps/irssi/src/silc/core/silc-cmdqueue.h [new file with mode: 0644]
apps/irssi/src/silc/core/silc-core.c
apps/irssi/src/silc/core/silc-lag.c
apps/irssi/src/silc/core/silc-queries.c
apps/irssi/src/silc/core/silc-servers.c
apps/irssi/src/silc/core/silc-servers.h
apps/silcd/Makefile.am
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/idlist.h
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/packet_send.h
apps/silcd/protocol.c
apps/silcd/route.c
apps/silcd/route.h
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_backup.c
apps/silcd/server_internal.h
apps/silcd/server_query.c
apps/silcd/server_util.c
apps/silcd/server_util.h
apps/silcd/server_version.c
apps/silcd/serverconfig.c
apps/silcd/serverid.c
apps/silcd/serverid.h
apps/silcd/silcd.c
config.guess
config.sub
configure.ad [moved from configure.in.pre with 78% similarity]
distdir/BSD [new file with mode: 0644]
distdir/BSD-header [new file with mode: 0644]
distdir/GPL [new file with mode: 0644]
distdir/GPL-header [new file with mode: 0644]
distdir/autodist [new file with mode: 0644]
distdir/autodist.conf [new file with mode: 0644]
distdir/client [new file with mode: 0644]
distdir/common [new file with mode: 0644]
distdir/default [new file with mode: 0644]
distdir/pre-run [new file with mode: 0644]
distdir/server [new file with mode: 0644]
distdir/toolkit [new file with mode: 0644]
distributions [deleted file]
doc/FAQ
doc/Makefile.ad [moved from doc/Makefile.am.pre with 56% similarity]
doc/draft-riikonen-presence-attrs-03.nroff [new file with mode: 0644]
doc/draft-riikonen-silc-commands-06.nroff
doc/draft-riikonen-silc-flags-payloads-04.nroff [new file with mode: 0644]
doc/draft-riikonen-silc-ke-auth-08.nroff [new file with mode: 0644]
doc/draft-riikonen-silc-pp-08.nroff
doc/draft-riikonen-silc-pp-09.nroff [new file with mode: 0644]
doc/draft-riikonen-silc-spec-08.nroff
doc/draft-riikonen-silc-spec-09.nroff [new file with mode: 0644]
doc/example_silcd.conf.in
doc/silcd.yo
doc/whitepaper/silc_protocol.html
includes/Makefile.ad [moved from includes/Makefile.am with 65% similarity]
includes/silcincludes.h.in
includes/silcversion.h.in [moved from includes/silcversion.h with 80% similarity]
lib/Makefile.ad [moved from lib/Makefile.am.pre with 58% similarity]
lib/configure.ad [new file with mode: 0644]
lib/contrib/Makefile.am
lib/contrib/gunicomp.h [new file with mode: 0644]
lib/contrib/gunidecomp.h [new file with mode: 0644]
lib/contrib/nfkc.c [new file with mode: 0644]
lib/contrib/rfc3454.c [new file with mode: 0644]
lib/contrib/stringprep.c [new file with mode: 0644]
lib/contrib/stringprep.h [new file with mode: 0644]
lib/doc/INDEX.tmpl
lib/doc/LIBINDEX
lib/doc/command_reply_args.html
lib/doc/notifyargs.html
lib/doc/silcclient_unicode.html [new file with mode: 0644]
lib/silc.pc.in [new file with mode: 0644]
lib/silcclient.pc.in [new file with mode: 0644]
lib/silcclient/DIRECTORY
lib/silcclient/Makefile.ad [moved from lib/silcclient/Makefile.am with 76% similarity]
lib/silcclient/client.c
lib/silcclient/client.h
lib/silcclient/client_attrs.c
lib/silcclient/client_channel.c
lib/silcclient/client_ftp.c
lib/silcclient/client_internal.h
lib/silcclient/client_keyagr.c
lib/silcclient/client_notify.c
lib/silcclient/client_ops_example.c
lib/silcclient/client_prvmsg.c
lib/silcclient/client_resume.c
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/idlist.c
lib/silcclient/protocol.c
lib/silcclient/protocol.h
lib/silcclient/silcclient.h
lib/silccore/Makefile.ad [moved from lib/silccore/Makefile.am with 82% similarity]
lib/silccore/silcargument.h
lib/silccore/silcattrs.c
lib/silccore/silcattrs.h
lib/silccore/silccommand.c
lib/silccore/silcidcache.c
lib/silccore/silcidcache.h
lib/silccore/silcmessage.h
lib/silccore/silcpacket.c
lib/silccore/silcstatus.h
lib/silccrypt/DIRECTORY
lib/silccrypt/Makefile.ad [moved from lib/silccrypt/Makefile.am with 81% similarity]
lib/silccrypt/ciphers.h
lib/silccrypt/pkcs1.c [deleted file]
lib/silccrypt/pkcs1.h [deleted file]
lib/silccrypt/rc6.c [deleted file]
lib/silccrypt/rc6.h [deleted file]
lib/silccrypt/rc6_internal.h [deleted file]
lib/silccrypt/rsa.c
lib/silccrypt/rsa.h
lib/silccrypt/rsa_internal.h
lib/silccrypt/silccipher.c
lib/silccrypt/silcpkcs.c
lib/silccrypt/silcpkcs.h
lib/silccrypt/silcpkcs1.c [new file with mode: 0644]
lib/silccrypt/silcpkcs1.h [new file with mode: 0644]
lib/silccrypt/silcrng.c
lib/silccrypt/silcrng.h
lib/silccrypt/tests/Makefile.am
lib/silccrypt/tests/test_silcpkcs.c [new file with mode: 0644]
lib/silcmath/Makefile.ad [moved from lib/silcmath/Makefile.am with 75% similarity]
lib/silcsftp/DIRECTORY
lib/silcsftp/Makefile.ad [moved from lib/silcsftp/Makefile.am with 76% similarity]
lib/silcsftp/sftp_client.c
lib/silcsftp/sftp_fs_memory.c
lib/silcsftp/sftp_server.c
lib/silcsftp/silcsftp.h
lib/silcsim/Makefile.ad [moved from lib/silcsim/Makefile.am with 86% similarity]
lib/silcske/Makefile.ad [moved from lib/silcske/Makefile.am with 74% similarity]
lib/silcutil/DIRECTORY
lib/silcutil/Makefile.ad [moved from lib/silcutil/Makefile.am with 81% similarity]
lib/silcutil/silcapputil.c
lib/silcutil/silcbuffmt.c
lib/silcutil/silcbuffmt.h
lib/silcutil/silcfileutil.c
lib/silcutil/silchashtable.c
lib/silcutil/silchashtable.h
lib/silcutil/silclist.h
lib/silcutil/silclog.c
lib/silcutil/silclog.h
lib/silcutil/silcmemory.h
lib/silcutil/silcnet.c
lib/silcutil/silcschedule.c
lib/silcutil/silcsockconn.c
lib/silcutil/silcsockconn.h
lib/silcutil/silcstringprep.c [new file with mode: 0644]
lib/silcutil/silcstringprep.h [new file with mode: 0644]
lib/silcutil/silcstrutil.c
lib/silcutil/silcstrutil.h
lib/silcutil/silctypes.h
lib/silcutil/silcutf8.c [new file with mode: 0644]
lib/silcutil/silcutf8.h [new file with mode: 0644]
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h
lib/silcutil/silcvcard.c
lib/silcutil/tests/Makefile.am [new file with mode: 0644]
lib/silcutil/tests/test_silchashtable.c [new file with mode: 0644]
lib/silcutil/tests/test_silcstringprep.c [new file with mode: 0644]
lib/silcutil/tests/test_silcstrutil.c [new file with mode: 0644]
lib/silcutil/unix/silcunixnet.c
lib/silcutil/unix/silcunixschedule.c
lib/silcutil/unix/silcunixsockconn.c
lib/silcutil/win32/silcwin32schedule.c
lib/silcutil/win32/silcwin32util.c
prepare [deleted file]
prepare-clean [deleted file]
scripts/silcdoc/silcdoc
tutorial/mybot/mybot.c
util/robodoc/Source/generator.c
win32/libsilc/libsilc.def
win32/libsilc/libsilc.dsp
win32/libsilc_static/libsilc_static.dsp
win32/libsilcclient/libsilcclient.def
win32/libsilcclient/libsilcclient.dsp
win32/libsilcclient_static/libsilcclient_static.dsp
win32/silcdefs.h

diff --git a/CHANGES b/CHANGES
index 06d20905e194009a33056066241d5d893c8b2e60..fa8a3230e41200c56bb8f9c066cb40328725e488 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,918 @@
+Sat Apr 16 20:23:48 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added Autodist.
+
+Thu Apr 14 20:25:08 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Handle empty LIST command reply correcttly in server.  Affected
+         file silcd/command_reply.c.
+
+       * Handle empty LIST command reply correctly in client library.
+         The application will now receive one LIST command reply with
+         all arguments set to NULL if there are no channels.  Updated
+         Client Library documentation accordingly.  Affected file
+         lib/silcclient/command_reply.c.
+
+Tue Apr 12 00:02:09 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added channel name string stringprep profile to the protocol
+         and implementation to allow a little free'er channel name
+         strings.  Affected files are lib/silcutil/silcstringprep.[ch].
+
+       * Added silc_channel_name_[check|verify] to check and verify
+         channel name strings.  Affected files are
+         lib/silcutil/silcstrutil.[ch].
+
+       * Added support for the new channel name preparation in client
+         library and server.  Affected files in lib/silcclient and
+         silcd/.
+
+Mon Apr 11 13:40:27 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added the Autodist into the source tree.  It replaces the
+         old ./prepare.  It can be used to create distributions as
+         previously.  See README.CVS and README.DIST.  See
+         distributions in distdir/.
+
+Sun Apr 10 11:30:56 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Make sure query sends at least an error back if nothing
+         more is sent.  Affected file silcd/server_query.c.
+
+Thu Apr  7 14:50:01 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * During query, check if the original command caller goes
+         away.  If it does, stop the query.  Affected file
+         silcd/server_query.c.
+
+       * Check for valid channel creation in JOIN command reply.
+         Affected file lib/silcclient/command_reply.c.
+
+       * Handle the resolver counter in silc_client_get_users_by_channel
+         callback correctly.  Fixed auto-join bug in Gaim.  Affected
+         file lib/silcclient/idlist.c.
+
+Wed Apr  6 16:56:53 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added some better error messages.  Affected file
+         silcd/command_reply.c and packet_receive.c.
+
+       * Handle error in WATCH command propely on backup router.
+         Affected file silcd/command.c.
+
+       * Fixed freeing of unfreeable variable in WHOIS command reply.
+         Affected file silcd/command_reply.c.
+
+Wed Apr  6 09:10:31 CEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added pkg-config .pc file creation for silc core library
+         and silcclient library.  A patch by c0ffee.
+
+       * Removed the need for GNU Libidn.  Added the simple stringprep
+         from libidn into lib/contrib/.  It is now used also on Windows
+         build.
+
+Mon Apr  4 15:15:46 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Simplified the invite and ban string handling in the
+         server.  Check for valid invite and ban arguments also.
+         Affected file silcd/server_util.c.
+
+Sun Apr  3 14:58:53 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added WATCH list announcing in backup router protocol.
+         Affected files are silcd/command.c, server.c, server_backup.c.
+
+       * Do not change users mode to founder on normal server/backup
+         if the founder mode is set, and user is first one to join.
+         Affected file silcd/pcaket_receive.c.
+
+       * Do not send CUMODE_CHANGE notify back to sender.  Affected
+         file silcd/packet_receive.c.
+
+       * Added getrusage() to take noise in SILC RNG.  A patch by
+         Mika Boström.  Affected files are configure.in.pre,
+         includes/silcincludes.h.in, lib/silccrypt/silcrng.c.
+
+Sat Apr  2 18:09:30 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Splitted the SILC libraries configuration into a configure
+         fragment into lib/configure.ad.  It is now possible, once
+         this feature is added, to specify whether to compile or not
+         compile included SILC libraries.  Affected files are
+         configure.in.pre, lib/silcmath/mpi/configure.ad,
+         lib/configure.ad, Makefile.defines.pre and
+         Makefile.defines_int.pre.
+
+       * Added --with-silc-includes and --with-silc-libs to configure.
+         If specified the included libs are not compiled, but the
+         specified libs are used.  Pkg-config is not yet supported.
+         Affected file configure.in.pre.
+
+       * Fixed WATCH command handling on backup router.  Router does not
+         send the watch command any more to backup if it originates from
+         backup.  Affected file silcd/command.c.
+
+Fri Apr  1 18:52:47 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Changed announcing to not announce unregistered clients.
+         Affected file silcd/server.c.
+
+       * Fixed username handling in command reply.  Affected file
+         silcd/command_reply.c.
+
+       * Log files are now 0600.  Affected file lib/silcutil/silclog.c.
+
+Thu Mar 31 22:34:22 CEST 2005  Patrik Weiskircher <pat@icore.at>
+
+       * Added new define SILC_MACOSX, if __APPLE__ and __MACH__ is defined.
+          Affected file: includes/silcincludes.h.in
+
+       * bool is defined as _Bool on Mac OS X now.
+          Affected file: lib/silcutil/silctypes.h
+
+Thu Mar 31 08:52:06 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for UTF-8 nicknames, channel names and
+         server names in client library.  Affected files in
+         lib/silcclient/.
+
+       * Added __SILC_HAVE_PTHREAD, __SILC_HAVE_SIM, __SILC_HAVE_LIBIDN,
+         and __SILC_ENABLE_DEBUG to include/silcclient.h for third-party
+         software to check how Toolkit has been compiled.
+
+Wed Mar 30 22:16:35 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added silc_utf8_str[n]casecmp into lib/silcutil/silcutf8.[ch].
+
+       * Use silc_utf8_str[n]casecmp instead of strcmp routines
+         in library and in SILC Client when dealing with nicknames
+         and other identifier strings.  Affected file in client lib
+         and irssi.
+
+       * Convert nickname to UTF-8 in /msg and /smsg.  Affected file
+         irssi/src/silc/core/silc-servers.c.
+
+Wed Mar 30 10:50:02 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed idcache to work with the new identifier strings.
+         Affected file lib/silccore/silcidcache.c.
+
+       * Added UTF-8 hash and compare function for SilcHashTable.
+         Affected file lib/silcutil/silcutil.[ch].
+
+       * Added casefolding stringprep, SILC_CASEFOLD_PREP.
+         Affected file lib/silcutil/silcstringprep.[ch].
+
+       * Changed the identifier string handling to include the original
+         format in client, server, channel entries and normalized
+         format in cache.  Affected files in silcd/.
+
+Tue Mar 29 16:51:35 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for the new identifier strings and their
+         validity checking.  Nicknames, channel names and usernames
+         can now include practically any kind of letters and various
+         other characters.  Affected files in silcd/ and in libraries.
+
+         NOTE: comparing these strings should now be done with memcmp()
+         to check binary compatibility.  All these strings are normalized
+         and casing is irrelevant.
+
+       * Added silc_identifier_check to lib/silcutil/silcstrutil.[ch]
+         as easy function for applications to check whether identifier
+         strings are valid.
+
+Tue Mar 29 00:45:11 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed SILC_STRING_LDAP_DN encoding and decoding.  Affected
+         file lib/silcutil/silcutf8.c.
+
+       * Added SILC_STRING_UTF8_ESCAPE to lib/silcutil/silcstrutil.h.
+
+Mon Mar 28 22:46:23 CEST 2005  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Make public key in getkey reply mandatory.  Affected file
+         lib/silcclient/command_reply.c
+
+Sun Mar 27 19:03:31 CEST 2005  Patrik Weiskircher <pat@icore.at>
+
+       * Added Parameter dont_register_crypto_library to
+         SilcClientParam. If set to TRUE, silcclient library will
+         not initalize the Crypto Libraries and application
+         will need to do it. Affected file lib/silcclient/silcclient.h,
+          lib/silcclient/client.c.
+
+Sun Mar 27 19:02:48 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Imported new silc_utf8_[encode|decode] routines from
+         my internal SILC 1.1 source tree.  New encodings added:
+         SILC_STRING_LOCALE (SILC_STRING_LANGUAGE is deprecated),
+         SILC_STRING_UTF8, SILC_STRING_PRINTABLE, SILC_STRING_VISIBLE,
+         SILC_STRING_TELETEX, SILC_STRING_NUMERICAL and
+         SILC_STRING_LDAP_DN.
+
+       * Splitted UTF-8 routines into lib/silcutil/silcutf8.[ch].
+
+       * Implemented stringprep (RFC 3454) API.  Internally we use
+         GNU Libidn's stringprep, for now, so it is required now to
+         compile SILC sources.  Added lib/silcutil/silcstringprep.[ch].
+
+       * Added checking for GNU Libidn and --with-libidn to configure.
+
+Wed Mar 23 11:20:33 CET 2005  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * If the passphrases entered do not match while generating a new key,
+         completly start over instead of going into an infinite loop asking
+         the user to re-enter the passphrase correctly.  Affected file
+         lib/silcutil/silcapputil.c
+
+Sun Jan  9 14:28:51 CET 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Make sure server is removed from backup list when it is
+         deleted.  Affected files silcd/command.c, server.c,
+         server_util.c.
+
+       * Close socket when connecting to router fails.  Affected
+         file silcd/server.c.
+
+Tue Jan  4 13:06:26 CET 2005  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Adopt configuration toolchain to current auto-tools.
+         Affected files prepare, irssi/configure.in
+       * Revert most of the UTF-8 fixes to SILC Client 1.0.1.  Will
+         redo that.  Affected files irssi/src/silc/core/client_ops.c,
+         irssi/src/fe-common/silc/fe-silc-channels.c
+       * Take over command line options into silcclient data structure.
+         Affected file irssi/src/silc/core/silc-core.c
+
+Wed Dec  8 16:15:11 CET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Do not try to initiate backup resuming protocol forever.
+         Affected file silcd/server_backup.c.
+
+Wed Nov 24 18:24:05 CET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * ID change in resuming has to be done before changing
+         detached client's modes, since the ID change may fail and
+         leave ghosts on the network.  Affected file is
+         silcd/packet_receive.c.
+
+Tue Nov 23 16:54:35 CET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed Win32 scheduler to not stuck anymore.  A patch from
+         Juha Räsänen.  Affected file is
+         lib/silcutil/win32/silcwin32schedule.c.
+
+       * Fixed QoS parsing for connection blocks in server.  Affected
+         file is silcd/serverconfig.c.
+
+       * Fixed server statistics increasing in server.  Affected file
+         is silcd/server.c.
+
+       * The CLOSE command now marks backup router as self disconnected
+         to avoid resuming problems.  Affected file silcd/command.c.
+
+Wed Sep 22 19:46:32 CEST 2004  Patrik Weiskircher <pat@icore.at>
+
+       * When using silc_net_create_connection[_async], and your system can
+         create IPv6 sockets, it will try to connect to the IPv6 host.
+         Now it tries to connect to an IPv4 host if IPv6 fails. Affected
+         file lib/silcutil/unix/silcunixnet.c
+
+Fri Jun 18 19:26:58 CEST 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Check for valid route when receiving packet from router and
+         when routing it to local server in the cell.  A patch from
+         Matt Miller.  Affected files silcd/router.c and server.c.
+
+Sat May  1 13:55:54 CEST 2004  Patrik Weiskircher <pat@icore.at>
+
+       * Couldn't detach and reattach twice, because of the previous
+         commit. Affected file silcd/packet_receive.c
+
+Fri Apr 30 19:40:28 CEST 2004  Patrik Weiskircher <pat@icore.at>
+
+       * Added check to ignore Port value if Initiator is FALSE.
+         Remote router coudln't connect if Port was set. Affected file
+         silcd/serverconfig.c
+
+       * If some client tries to resume more than once at the same time,
+         server crashed. Router didn't crash, but showed odd behaviour
+         (didn't allow clients to join anymore, ..). Affected files
+         silcd/packet_receive.c silcd/idlist.h
+
+Mon Mar 15 21:10:08 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Destroy the file transfer session in silc_client_file_close
+         with timeout.  Affected file lib/silcclient/client_ftp.c.
+
+       * Call SFTP server monitor in READ and WRITE after the actual
+         operations.  Affected file lib/silcsftp/sftp_server.c.
+
+Wed Mar 10 21:30:02 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Create one configure script from configure fragments
+         (configure.ad).  This is a first step towards new distribution
+         system.  Affected files prepare, configure.in.pre,
+         lib/silcmath/mpi/configure.ad.
+
+Wed Mar 10 18:35:24 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Removed expiring of client key pair.  Affected file is
+         irssi/src/silc/core/clientutil.c
+
+Tue Mar  9 17:11:58 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Check the number of connections from real number of
+         connections instead of socket number, when deciding if
+         server is full.  Affected files are silcd/server.c,
+         server_internal.h and silcd.c.
+
+       * Clarified the connections_max meaning in General section
+         in doc/example_silcd.conf.in.
+
+       * The reconnect_keep_trying default value set to TRUE
+         if it is not defined in the config file.  Affected file
+         silcd/serverconfig.c.
+
+Wed Mar  3 15:13:49 CET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed crashbug in connection closing, after a protocol
+         completion callback, which might have closed it already.
+         Affected file silcd/server.c.
+
+       * Fixed rekey with PFS in backup router.  It did not allow
+         rekeys with PFS, and when the rekey protocol timedout
+         it crashed the backup router without the above fix.  Affected
+         file silcd/packet_send.c and server.c.
+
+Sat Feb 28 16:25:09 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * The silc_client_add_channel_private_key now returns the
+         private key context if pointer is given as argument.
+         Affected files are lib/silcclient/silcclient.h and
+         client_channel.c.
+
+       * Added support for using channel private keys in SILC
+         Client Library even if the private key mode is not set
+         on the channel.  Affected file lib/silcclient/client_channel.c.
+
+       * The channel private key used to decrypt message is now
+         delivered to the application in the 'channel_messageÃ' client
+         operation.  Affected files are lib/silcclient/silcclient.h
+         and client_channel.c.
+
+       * Fixed wrong arg type for user limit in CMODE command reply.
+         Affected file silcd/command.c.
+
+       * The user limit is now taken and saved to SilcClientEntry in
+         JOIN and CMODE command replies and in CMODE_CHANGE notify.
+         Affected files lib/silcclient/silcclient.h, command_reply.c
+         and client_notify.c.
+
+       * Added support to the new private message key indicator
+         packet.  Added a new function to the client library:
+         silc_client_send_private_message_key_request.  The sender
+         indicates to be initiator, and receiver is responder.
+         Added the indicator to the SilcClientEntry as 'prv_resp'
+         boolean.  Affected files are lib/silcclient/silcclient.h
+         client.[ch], and client_prvmsg.c.
+
+Fri Feb 27 11:25:26 CET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed the JOIN command calling when called with both
+        -auth and -founder.  Affected file is lib/silcclien/command.c.
+
+Wed Feb 25 23:12:11 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Check watcher list for resumed clients as well.  Affected
+         file is silcd/packet_receive.c.
+
+Tue Feb 24 16:49:10 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Implemented the user limit to the CMODE_CHANGE notify,
+         CMODE command reply and JOIN command reply in server.
+         Affected files are silcd/server.c, command.c, command_reply.c,
+         packet_send.c and packet_receive.c.
+
+Mon Feb 23 23:31:15 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Defined SILC_STRFMT_END that must be used now with
+         silc_buffer_strformat, instead of SILC_STR_END.  Fixes
+         crashes on AMD64.  Affected files are lib/silcutil/silcbuffmt.h,
+         lib/silcclient/silcvcard.c, silcd/server_util.c.
+
+       * Fixed the adding of public key to the WATCH list in server.
+         Fixed the WATCH notify sending to client.  Affected files
+         are silcd/packet_send.[ch], command.c, server_util.c.
+
+       * Implemented the watching by public key in the SILC Client
+         Library and SILC Client.  Affected files are
+         lib/silcclient/command.c and client_notify.c.
+
+Mon Feb 23 09:30:30 CET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for public key watching in server.  Affected
+         files are silcd/server.c, server_internal.h, command.c,
+         server_util.c.
+
+Sun Feb 22 19:03:59 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added public key to the SIlcClientEntry.  Affected files
+         are lib/silcclient/silcclient.h, command_reply.c, idlist.c
+
+       * Fixed the get_clients_whois reply processing to return
+         exactly same entries server returned.  Makes it possible
+         to search using attributes.  Affected file is
+         lib/silcclient/idlist.c.
+
+Sat Feb 21 19:21:57 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Save founder key to SilcChannelEntry.  Affected files are
+         lib/silcclient/silcclient.h, command_reply.c, idlist.c.
+
+Fri Feb 20 20:37:38 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Call the monitor callback with _CLOSED status from the
+         silc_client_file_close.  Affected files are
+         lib/silcclient/client_fpt.c, silcclient.h
+
+       * Added silc_client_get_clients_whois which resolves using
+         WHOIS, and supports requested attributes as well.
+         Affected files are lib/silcclient/silcclient.h, idlist.c.
+
+Fri Feb 19 21:09:22 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for asking the destination filename where
+         the downloaded file is saved in the file transfer.  Affected
+         files are lib/silccilent/silcclient.h, client_ftp.c.
+
+Wed Feb 18 02:46:17 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed error handling in resuming data processing.  Affected
+         files are lib/silcclient/client_resume.c and client.c.
+
+Tue Feb 17 19:34:30 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed silc_client_send_private_message to return TRUE correctly.
+         Affected file lib/silcclient/client_prvmsg.c.
+
+       * Added topic to the SilcChannelEntry.  Affected files are
+         lib/silcclient/silcclient.h, command_reply.c, client_notify.c.
+
+Fri Feb 13 14:19:14 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Use conn->cmd_ident for all silc_client_command_call()s.  Affected
+         file lib/silcclient/command.c
+
+Fri Feb 13 13:53:45 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Convert all commands to UTF-8 before passing them to the
+         client library.  Still need to convert replies from UTF-8 to
+         the locale encoding.  Affected file
+         irssi/src/silc/core/silc-cmdqueue.c
+
+Fri Feb 13 13:13:07 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * redirect all silc_client_command_calls through a queueing framework.
+         This fixes /CYCLE and the annoying "nick change after auto-joining
+         a channel".  Furthermore it defines one central point where
+         command parameters can be UTF-8-ified.  Affected files
+         irssi/src/silc/core/Makefile, client_ops.c, silc-channels.c,
+         silc-servers.[ch], silc-core.c, silc-cmdqueue.[ch], silc-lag.c
+
+Fri Feb 13 12:04:41 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * use asynchronous connect() to establish router connections.
+         Fixes problem when the primary router goes down.  Affected files
+         silcd/server.c, silcd/server_backup.c
+
+Thu Feb 12 20:09:59 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added SILC_[32|64]_TO_PTR and SILC_PTR_TO_[32|64] macros.
+         Fixed various compilation warnings when type casting ints
+         to pointers or vice versa, of different size.  Updates around
+         the source free.
+
+Tue Feb  3 23:25:17 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Surrogates not allowed in UTF-8 strings, updated decoder.
+         Affected file lib/silcutil/silcstrutil.c.  Added UTF-8
+         testers in lib/silcutil/tests/ directory.
+
+Wed Jan 14 18:42:44 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added SILC_CLIENT_CONN_ERROR_KE, ERROR_AUTH, ERROR_RESUME and
+         ERROR_TIMEOUT SilcClientConnectionStatus errors.  Affected
+         files are lib/silcclient/silcclient.h, client.c.
+
+Mon Jan 12 13:01:10 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * When resuming a session fails, notify the user that the session
+         file needs to be removed eventually.  Affected files
+         irssi/src/fe-common/silc/module-formats.[ch],
+         irssi/src/silc/core/client_ops.c.
+
+Tue Jan 04 12:16:04 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Added DIST_SUBDIRS symbols to include all subdirs in distributions.
+         Affected files lib/silcutil/Makefile.am, lib/silcmath/Makefile.am
+
+       * Typofix in Irssi::Silc module.  Affected file
+         irssi/src/perl/silc/Silc.xs.
+
+Tue Jan 04 02:43:44 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Changed the way NOTICE flagged messages are treated. Added support
+         for notices in queries and signing notices.  Affected files
+         irssi/default.theme; irssi/docs/help/in/notice.in;
+         irssi/src/fe-common/silc/module-formats.[ch], fe-silc-messages.c;
+         irssi/src/silc/core/client_ops.c, silc-channels.c, silc-servers.c
+
+       * Fixed typo in /ACTION help.  Affected file
+         irssi/docs/help/in/action.in
+
+Mon Jan 03 23:26:38 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Fixed typo in perl module.  Affected file
+         irssi/src/perl/silc/Server.xs
+
+       * Changed the way ACTION flagged messages are treated. Added support
+         for actions in queries and signing actions.  Affected files
+         irssi/default.theme; irssi/docs/help/in/action.in;
+         irssi/src/fe-common/silc/module-formats.[ch], fe-silc-messages.c,
+         fe-silc-queries.c; irssi/src/silc/core/client_ops.c, silc-channels.c,
+         silc-servers.[ch]
+
+Mon Jan 03 16:04:29 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Incorrectly reported error when client had to be resolved from
+         server in /SMSG.  Affected file irssi/src/silc/core/silc-servers.c
+
+Sat Jan  3 16:37:15 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed whois public key hash table deleting and adding in
+         detached client case.  Affected file silcd/packet_receive.c.
+
+Sat Jan 03 12:15:38 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Changed filenames of silc/fe module not to collide with filenames
+         from core/fe.  Also seperated public messages printing from
+         query messages printing.  Affected files are all in
+         irssi/src/fe-common/silc.
+
+Sat Jan  3 12:18:07 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed the invite process handling during joining to use
+         correct server name for the client that is matched against
+         the invite string for the channel.  Wrong server name caused
+         inability to join the channel.  Affected file is
+         silcd/command.c.
+
+Fri Jan  2 23:34:17 EET 2004  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed the CUMODE channel founder authentication on normal
+         server to not remove the founder rights on existing founder
+         before checking that router accepts the mode change.  Affected
+         files are silcd/command.c and silcd/packet_receive.c.
+
+       * Remove the server entry correctly when rekey timeouts and
+         remote router connection on normal server is closed.  Fixes
+         a crash where server uses the freed server entry.  Affected
+         file silcd/server.c.
+
+Fri Jan 02 10:28:15 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Add /SILCNET [ADD|REMOVE|LIST] command to manage different SILC
+         networks.  This is the first step in solving the bug about
+         /SERVER ADD -silcnet <silcnet>.  Affected files
+         irssi/docs/in/silcnet.in; irssi/src/fe-common/silc/Makefile.am,
+         fe-silcnet.c, fe-common-silc.c, module-formats.[ch];
+         irssi/src/silc/core/silc-chatnets.[ch], silc-core.c, Makefile.am
+
+Thu Jan 01 20:11:32 CET 2004  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * /SMSG and /MMSG now correctly create new queries. Affected files
+         irssi/src/fe-common/silc/fe-messages.c, irssi/scripts/silc-mime.pl
+
+       * Add basic support for SILC protocol specific variables in perl.
+         Affected files irssi/src/perl/silc/*, irssi/configure.in,
+         irssi/src/perl/Makefile.am
+
+Wed Dec 31 17:06:55 CET 2003  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Don't use silc_get_input, it's obviously not reliable.  Fixes
+         issue when the current key expires.  Affect file
+         irssi/src/silc/core/clientutils.c
+
+       * Make the session data filename configurable.  This makes it
+         possible to have different session files for different
+         SILC networks.  Affected files irssi/src/silc/core/silc-core.c,
+         client_ops.[ch], silc-servers.c,
+         irssi/src/silc/fe-common/silc/module-formats.[ch]
+
+       * Use the same set of libtool files for the MPI lib as for the
+         rest of the toolkit.  Affected files lib/silcmath/mpi/config.guess,
+         config.sub, configure.in, install-sh, missing, mkinstalldirs
+
+Sun Dec 28 21:57:39 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed server statistics decrementing error to not go to
+         negative.  Affected file silcd/packet_receive.c.
+
+Sat Dec 20 14:42:36 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Use silc_server_query_add_error to add error in public key
+         search error.  Added support in send_reply to send errors
+         without specific argument.  Affected file silcd/server_query.c.
+
+       * Fixed the WHOIS, IDENTIFY and WHOWAS error handling in SILC
+         Client for NO_SUCH_NICK.  It was against the protocol specs.
+         Affected file irssi/src/silc/core/client_ops.c.
+
+       * Added backwards support for the wrong NO_SUCH_NICK error sending
+         in server.  To be removed in SILC Server 1.0.  Both old clients
+         and clients with fixed error handling now works.  Affected file
+         silcd/server_query.c.
+
+Sat Dec 20 00:44:47 CET 2003  Patrik Weiskircher <pat@icore.at>
+
+       * fixed a bug in the whois using attributes function where no
+         error was sent if no nickname and client id but the attributes were
+         given to whois. Affected file silcd/server_query.c
+
+Tue Dec 16 21:34:59 CET 2003  Patrik Weiskircher <pat@icore.at>
+
+       * remove public key from public key hashtable on detach. Affected
+         file silcd/packet_receive.c
+
+       * free public key hashtable before removing clients on server
+         shutdown. Affected file silcd/server.c
+
+       * remove public key prior deleting client-data on killing a client.
+         Affected file silcd/server_util.c
+
+Sat Dec 06 21:35:14 CET 2003  Patrik Weiskircher <pat@icore.at>
+
+       * Getting the MOTD from other servers works now. Affected
+         files are silcd/command.c and silcd/command_reply.c
+
+Thu Dec 04 11:33:46 CET 2003  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Initialize the variable idletag, since it is tested in
+         silc_core_deinit for its default value.  Affected file
+         irssi/src/silc/core/silc-core.c
+
+Sun Nov 30 19:47:02 CET 2003  Patrik Weiskircher <pat@icore.at>
+
+       * Fixed signed channel messages across cells. Affected file
+         silcd/packet_send.c
+
+Fri Nov 28 19:13:21 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Changed the SILC_LOG_* macros to not be empty if SILC_DEBUG
+         is not defined.  They can now be safely used in if-statements
+         without braces.  Affected file lib/silcutil/silclog.h.
+
+       * Added the checks for backup closing connection due to error
+         (local or remote) and thus not allow the resuming to occur
+         in reconnect.  Affected files are silcd/packet_send.c
+         and server.c.
+
+Tue Nov 25 15:20:59 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Help file updates.  Affected files in irssi/src/docs/help/in/.
+
+Wed Nov 23 20:51:21 CET 2003  Patrik Weiskircher <pat@icore.at>
+
+       * Fixed channel messages across cells. Affected file
+         silcd/packet_send.c
+
+Wed Nov 12 11:34:56 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed file transmission accepting in client library to not
+         start the negotiation if user hasn't accepted the transfer,
+         instead create new session for resent transfer.  Affected
+         file lib/silcclient/client_ftp.c.
+
+       * Show the session ID in the file transmision list.  Remove
+         session from list that failed to transfer.  Switch the current
+         session automatically after transmission, and in errors, to new
+         session if other sessions exists in the transfer list.  Affected
+         files are irssi/src/silc/core/silc-servers.c,
+         irssi/src/fe-common/silc/modfule-formats.c.
+
+Mon Nov 10 14:41:40 CET 2003  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Fixed MIME header parsing for the hopefully last time.  Affected
+         file lib/silcutil/silcstrutil.c
+
+Mon Nov 10 13:03:46 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Rewrote the PKCS#1 routines.  Added lib/silccrypt/silcpkcs1.[ch].
+
+       * The SILC RNG is now gauranteed to return non-zero random
+         values.  Affected files are lib/silccrypt/silcrng.[ch].
+
+Sun Nov  9 20:44:56 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed nickname formatting when changing only case of the
+         nickname.  Affected file lib/silcclient/idlist.c.
+
+Sun Nov  9 19:33:59 CET 2003  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Fixed a memory leak and incorrect printing of the "appears as"
+         message.  Affected file irssi/src/silc/core/client_ops.c
+
+Sun Nov  9 17:45:11 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added CRT (Chinese Remainder Theorem) supported RSA
+         private keys and private key operations.  This significantly
+         increases private key operation efficiency.  No compatibility
+         issues with new or old private keys.  Affected files are
+         lib/silccrypt/rsa.[ch], rsa_internal.h and pkcs1.c.
+
+Sat Nov  8 13:08:53 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed GCC-3.3.2 related compilation warnings from the
+         source tree.
+
+Fri Nov  7 23:01:47 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Removed RC6 from distributions.
+
+Fri Nov  7 19:38:42 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added some better comments to lib/silccrypt/silcpkcs.h,
+         optimized some routines in lib/silccrypt/silcpkcs.c.
+         Added test_silcpkcs into lib/silccrypt/tests/.
+
+       * Fixed silc_rng_global_init to actually init the global RNG
+         if RNG wasn't provided for it.  Affected file is
+         lib/silccrypt/silrng.c.
+
+Thu Nov  6 21:08:28 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added silc_hash_table_find_by_context_ext.  Affected files
+         lib/silcutil/silchashtable.[ch].
+
+       * Save the public key on normal server in WHOIS command reply
+         from attributes, if present, and add it to public key hash
+         table.  Fixes WHOIS resolving by public key on normal server.
+
+         Optimized the attributes resolving on normal server to not
+         resolve if we resolved them already from router.
+
+         Affected files are silcd/server_query.c, command_reply.c.
+
+Wed Nov  5 19:36:30 CET 2003 Patrik Weiskircher <pat@icore.at>
+
+       * Added support for whois using attributes.
+         Affected files silcd/command_reply.c, silcd/packet_receive.c,
+         silcd/server.c, silcd/server_internal.h, silcd/server_query.c,
+         silcd/server_util.c
+
+       * Added support for whois using public key attribute to /WHOIS i
+         client command. Affected files irssi/docs/help/in/whois.in,
+         irssi/src/silc/core/silc-servers.c, lib/silcclient/command.c
+
+Wed Nov  5 23:37:36 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed UMODE setting in server when the client has anonymous
+         mode set.  The mode setting was not working.  Affected file
+         silcd/command.c.
+
+Mon Nov  2 11:36:08 CET 2003 Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Fixed some bugs and typos related to sending split messages.
+          Print notification when sending messages with /MMSG.  Affected
+         files irssi/scripts/silc-mime.pl, irssi/src/silc/core/client_ops.c
+
+Fri Oct 31 12:33:59 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+       * Optimized the socket referencing in packet routines, client
+         library and server.  Affected files are lib/silccore/silcpacket.c,
+         lib/silcclient/client.c and silcd/server.c.
+
+       * If silc_socket_set_qos is given with NULL arguments the QoS is
+         reset from the socket.  Affected files are
+         lib/silcutil/silcsockconn.[ch].
+
+Thu Oct 30 21:23:24 CET 2003 Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Add a /LISTKEYS command which lists the locally cached
+         client and server keys.  Affected files
+         irssi/src/fe-common/module-formats.[ch],
+         irssi/src/silc/core/silc-{channels,servers}.c
+         irssi/docs/help/in/listkeys.in
+
+Thu Oct 30 20:23:40 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+       * Check that packet queue purging was successful.  Affected
+         files lib/silcclient/client.c and silcd/packet_send.c.  Related
+         to MAC failed errors.
+
+       * Do not clear the inbuf even if it is empty if QoS was applied
+         to it.  Otherwise the QoS data is cleared and MAC failed error
+         will occur.  Affected file lib/silccore/silcpacket.c.
+
+       * Use the rekey period time as rekey protocol timeout value.
+         If the rekey does not succeed during the rekey period there's
+         something very wrong, and we most likely end up with wrong keys,
+         do graceful reconnect then.   Affected file silcd/server.c.
+
+       * Take reference of the socket in the parser context, as it's
+         possible to have the parsers in queue after the socket is
+         disconnected and this may cause crash.  Affected files are
+         lib/silccore/silcpacket.c, lib/silcclient/client.c and
+         silcd/server.c.
+
+Thu Oct 30 17:01:01 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed KICK command reply sending, it sent to replies.
+         Affected file silcd/command.c.
+
+Wed Oct 30 14:06:52 CET 2003 Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Finish the silc-mime.pl script. It now supports MIME type
+         guessing using magic files, signing data messages, executing
+         MIME handlers in background. Affected files
+         irssi/scripts/silc-mime.pl and irssi/docs/help/in/mmsg.in
+
+       * Changed MIME signal handler to make things easier for the perl
+         script. Affected files irssi/src/silc/core/client_ops.c,
+         silc-servers.c, and irssi/docs/signals.txt
+
+       * Cleaned up the silc_mime_parse function and fixed detection
+         of wrapped header lines. Affected file lib/silcutil/silcstrutil.c
+
+Sun Oct 26 21:19:02 EET 2003 Pekka Riikonen <priikone@silcnet.org>
+
+       * Resolve the IP for file transfer listener from the connection
+         socket.  Affected file lib/silcclient/client_ftp.c.
+
+       * Accept NULL hostname parameter in the functions
+          silc_net_check_[local|remote]_by_socket.  Do not reverse lookup
+         if hostname is not wanted.
+
+Fri Oct 24 21:24:12 CEST 2003  Jochen Eisinger <jochen@penguin-breeder.org>
+
+       * Fixed race condition between silc_client_init and
+          my_silc_scheduler. Affected file irssi/src/silc/core/silc-core.c
+
+Fri Oct 24 16:43:40 EEST 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed file transfer connection closing when SIGNOFF for
+         the client is received from server.  Affected file is
+         lib/silcclient/client_ftp.c.
+
+Tue Oct 21 13:35:57 CEST 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Check for disconnected socket in QUIT callback.  Affected
+         file silcd/command.c.
+
+Thu Oct 21 09:43:17 CEST 2003  Jochen Eisinger <jochen@penguin-breeder.org>
+
+        * Modified the MIME parsing to allow \n and \r\n as delimiters.
+         Affected files lib/silcutil/silcstrutil.c
+
+       * Cleaned up the escape/unescape functions for correctness and
+         speed. Affected file irssi/src/silc/core/client_ops.c
+
+       * Removed handling for data messages with Content-Type: text/*,
+         moved parsing of MIME headers to the signal handler, added
+         support for signing and verifying data messages. Affected
+         files are irssi/docs/signals.txt, irssi/src/silc/core/client_ops.c,
+         irssi/src/silc/core/silc-{servers,channels}.c
+
+       * Added a perl script for handling data messages based on
+         information read from Mailcap files. New file
+         irssi/scripts/silc-mime.pl
+
+Mon Oct 20 16:08:22 EEST 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added new SILC_MESSAGE_FLAG_ACK that can  be used to
+         acknowledge recepetion of a message to the sender.  Updated
+         protocol specs.
+
+Sat Oct 18 11:55:33 EEST 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Unregister channel key saving callback when deleting channel.
+         Affected file lib/silcclient/idlist.c.
+
+       * Do not remove the client from channels in NOTIFY_TYPE_SIGNOFF
+         before calling notify client operation.  Affected file is
+         lib/silcclient/client_notify.c.
+
+       * Unregister QoS tasks when deleting the socket connection.
+         Affected files lib/silcutil/silcsockconn.[ch],
+         unix/silcunixsockconn.c.
+
+       * Implemented latest presence-attrs draft changes.  Affected
+         files lib/silccore/silcattrs.h and
+         irssi/src/silc/core/silc-queries.c.
+
 Tue Oct 14 18:24:53 EEST 2003  Pekka Riikonen <priikone@silcnet.org>
 
        * Save old channel keys in list to allow more rapid change
diff --git a/CREDITS b/CREDITS
index 950df4ab24aa10282d2339a559a254564637a40c..9d5c34646d00af8f47ccac7b2dbb2ea43645a215 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -33,9 +33,17 @@ S: Skinnarilankatu 28 E 2
 S: 53850 Lappeenranta
 S: Finland
 
+N: Jochen "c0ffee" Eisinger
+E: jochen@penguin-breeder.org
+W: http://penguin-breeder.org/
+D: maintainer of the SILC Client & SILC Plugin
+D: several new subtle bugs disguised as fixes and patches
+S: Haslacher Str. 45
+S: 79115 Freiburg
+S: Germany
+
 N: Giovanni Giacobbi
 E: giovanni@giacobbi.net
-E: johnny@themnemonic.org
 P: 1024D/B2D79FC1 6247 640C 1C90 1EE4 D800  E4E2 2D58 3DF1 B2D7 9FC1
 D: silcconfig, silclog, various patches around
 D: RPM packages
@@ -44,7 +52,7 @@ S: Italy
 
 N: Pekka Riikonen
 E: priikone@silcnet.org
-E: priikone@ssh.com
+E: priikone@iki.fi
 P: 1024/A924ED4F AD 82 53 2D 84 FF C7 D1  FF 63 19 0E 1A 78 9F 8A  A9 24 ED 4F
 D: Protocol architect
 D: Main developer
@@ -69,15 +77,15 @@ D: Bughunting
 
 N: Lubomir Sedlacik
 E: salo@Xtrmntr.org
+E: salo@NetBSD.org
 W: http://Xtrmntr.org
-P: 1024/7E3B70E2 DB EC 8B EC 9A 90 EC EC  0F EF 71 6E 59 CE B7 0B  7E 3B 70 E2
-D: web pages
+P: 1024/54BC7263 75 B2 2B 96 CD 75 03 85  1C 49 39 B8 8B 08 C3 0E  54 BC 72 63
 D: configure.in bugfixes
-D: NetBSD and Solaris packages
+D: NetBSD packages
 D: project server administrator
 D: mirrors coordinator
-S: 92101 Piestany
-S: Slovakia
+S: 15000 Prague
+S: Czech Republic
 
 N: Timo Sirainen
 E: tss@iki.fi
@@ -105,13 +113,21 @@ S: Arnyas ut 38-40/H
 S: 1121 Budapest
 S: Hungary
 
+N: Patrik Weiskircher
+E: pat@icore.at
+P: 1024D/BF475975 3240 EE43 E979 C5B9 981F  12D5 EC14 B9CD BF47 5975
+D: patch for whois using attributes
+S: Kandlgasse 17/3
+S: 1070 Vienna
+S: Austria
+
 N: Toni Willberg
 W: http://toniw.iki.fi/
 E: toniw@iki.fi
-D: bugzilla.silcnet.org admin
-D: silc.peelo.com admin
-D: Silc Admin development
-D: Testing
+D: silc.atbusiness.com admin
+D: www.fi.silcnet.org admin
+D: Hunting the client library bugs while developing Silky.
+D: General whining.
 S: Helsinki
 S: Finland
 
diff --git a/INSTALL b/INSTALL
index 25b5ea0464df3caf400658aba5d3891200bef981..a6c12c0799ed300ab3ffda11b0aa68bcd350d49a 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -32,7 +32,7 @@ path in your system which contains lib/ and include/ for GMP library.
 GMP can be used as a fall-back if you have problems with the MPI library
 included within this package.
 
-'--with-iconv[=DIR]'
+`--with-iconv[=DIR]'
 
    If your system doesn't provide iconv() function in its native libraries
 (usually libc) or if this function is broken (e.g. older Solaris systems),
similarity index 68%
rename from Makefile.am.pre
rename to Makefile.ad
index 2c1eae371f80b3ea10812edaba96cadf677785f6..1ffcbca2bd4e42140935430d44abfca22d678523 100644 (file)
@@ -1,9 +1,9 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
 #  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 - 2003 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-COMMONDIRS = lib irssi silc silcd doc includes
-
-# Sub directories defined by "distributions" file, and can be overridden
-# with ./configure, which substitutes these variables.
-SUBDIRS = @SILC_DIST_SUBDIRS@
-DIST_SUBDIRS = @SILC_DIST_SUBDIRS@
-
-include $(top_srcdir)/Makefile.defines.in
-
-dist-bzip: distdir
-       -chmod -R a+r $(distdir)
-       -tar chof $(distdir).tar $(distdir)
-       -bzip2 $(distdir).tar
-       -rm -rf $(distdir)
-
-SILC_EXTRA_DIST = SILC_DISTRIBUTION_EXTRA
-EXTRA_DIST = libtoolfix CHANGES CREDITS $(SILC_EXTRA_DIST)
-
+SUBDIRS =              \
+#ifdef SILC_DIST_APPS
+       apps            \
+#endif SILC_DIST_APPS
+#ifdef SILC_DIST_LIB
+       lib             \
+#endif SILC_DIST_LIB
+#ifdef SILC_DIST_CLIENT
+       irssi           \
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_SERVER
+       silcd           \
+#endif SILC_DIST_SERVER
+#ifdef SILC_DIST_TOOLKIT
+       silc            \
+       win32           \
+#endif SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_INCLUDES
+       includes        \
+#endif SILC_DIST_INCLUDES
+#ifdef SILC_DIST_DOC
+       doc
+#endif SILC_DIST_DOC
+
+EXTRA_DIST =           \
+       silcdefs.h.in   \
+#ifdef SILC_DIST_SILC
+#ifdef SILC_DIST_TOOLKIT
+       README.CVS README.WIN32 README.MACOSX silcer tutorial \
+#endif SILC_DIST_TOOLKIT
+       libtoolfix      \
+       CHANGES CREDITS
+#endif SILC_DIST_SILC
+
+#ifdef SILC_DIST_SILC
 #
 # Installing of SILC into the system
 #
 
-etcdir = $(DESTDIR)$(silc_etcdir)
-modulesdir = $(DESTDIR)$(silc_modulesdir)
-helpdir = $(DESTDIR)$(silc_helpdir)
-docdir = $(DESTDIR)$(silc_docdir)
-logsdir = $(DESTDIR)$(silc_logsdir)
-mandir = $(DESTDIR)@mandir@
-
 install-dirs:
        -mkdir -p $(etcdir)
        -mkdir -p $(modulesdir)
        -mkdir -p $(docdir)
 
-install-dirs-client: install-dirs
-       -mkdir -p $(helpdir)
-       -mkdir -p $(mandir)/man1
-
-install-dirs-server: install-dirs
-       -mkdir -p $(logsdir)
-       -mkdir -p $(mandir)/man5
-       -mkdir -p $(mandir)/man8
-
 doc-install:
        -$(INSTALL_DATA) $(srcdir)/doc/CodingStyle $(docdir)/
        -$(INSTALL_DATA) $(srcdir)/doc/FAQ $(docdir)/
@@ -71,12 +72,37 @@ doc-install:
        -$(INSTALL_DATA) $(srcdir)/INSTALL $(docdir)/
        -$(INSTALL_DATA) $(srcdir)/TODO $(docdir)/
 
+#ifdef SILC_DIST_SIM
+sim-install:
+       -$(INSTALL_DATA) $(srcdir)/lib/silcsim/*.so $(modulesdir)/
+#endif SILC_DIST_SIM
+
+#ifdef SILC_DIST_CLIENT
+install-dirs-client: install-dirs
+       -mkdir -p $(helpdir)
+       -mkdir -p $(mandir)/man1
+
 doc-install-client: doc-install
        $(INSTALL_DATA) $(srcdir)/irssi/silc.conf $(docdir)/example_silc.conf
        -@if test -f $(srcdir)/doc/silc.1 ; then \
         $(INSTALL_DATA) $(srcdir)/doc/silc.1 $(mandir)/man1; \
        fi
 
+etc-install-client:
+       -@if test '!' -d $(srcdir)/irssi ; then \
+         if test '!' -f $(etcdir)/silc.conf ; then \
+           $(INSTALL_DATA) $(srcdir)/irssi/silc.conf \
+               $(etcdir)/silc.conf; \
+         fi; \
+       fi
+#endif SILC_DIST_CLIENT
+
+#ifdef SILC_DIST_SERVER
+install-dirs-server: install-dirs
+       -mkdir -p $(logsdir)
+       -mkdir -p $(mandir)/man5
+       -mkdir -p $(mandir)/man8
+
 doc-install-server: doc-install
        -$(INSTALL_DATA) $(srcdir)/doc/example_silcd.conf $(docdir)/
        -@if test -f $(srcdir)/doc/silcd.8 ; then \
@@ -86,14 +112,6 @@ doc-install-server: doc-install
         $(INSTALL_DATA) $(srcdir)/doc/silcd.conf.5 $(mandir)/man5; \
        fi
 
-etc-install-client:
-       -@if test '!' -d $(srcdir)/irssi ; then \
-         if test '!' -f $(etcdir)/silc.conf ; then \
-           $(INSTALL_DATA) $(srcdir)/irssi/silc.conf \
-               $(etcdir)/silc.conf; \
-         fi; \
-       fi
-
 etc-install-server:
        -@if test '!' -f $(etcdir)/silcd.conf ; then \
          $(INSTALL_DATA) $(srcdir)/doc/example_silcd.conf \
@@ -103,15 +121,6 @@ etc-install-server:
           chmod go= $(etcdir)/silcd.conf; \
        fi
 
-sim-install:
-       -$(INSTALL_DATA) $(srcdir)/lib/silcsim/*.so $(modulesdir)/
-
-toolkit-install:
-       -mkdir -p $(docdir)/toolkit/
-       -$(INSTALL_DATA) $(srcdir)/doc/toolkit/* $(docdir)/toolkit
-       -$(INSTALL_DATA) $(srcdir)/lib/doc/*.gif $(docdir)/toolkit
-       -cp -R $(srcdir)/tutorial $(prefix)
-
 examples-install:
        -mkdir -p $(docdir)/examples/
        -$(INSTALL_DATA) $(srcdir)/doc/examples/README $(docdir)/examples/
@@ -121,13 +130,36 @@ generate-server-key:
        -@if test '!' -f $(etcdir)/silcd.pub ; then \
          $(sbindir)/silcd -C $(etcdir); \
        fi
+#endif SILC_DIST_SERVER
+
+#ifdef SILC_DIST_TOOLKIT
+toolkit-install:
+       -mkdir -p $(docdir)/toolkit/
+       -$(INSTALL_DATA) $(srcdir)/doc/toolkit/* $(docdir)/toolkit
+       -$(INSTALL_DATA) $(srcdir)/lib/doc/*.gif $(docdir)/toolkit
+       -cp -R $(srcdir)/tutorial $(prefix)
+#endif SILC_DIST_TOOLKIT
+
+install-data-hook:             \
+#ifdef SILC_DIST_CLIENT
+       install-dirs-client     \
+       doc-install-client      \
+       etc-install-client      \
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_SERVER
+       install-dirs-server     \
+       doc-install-server      \
+       etc-install-server      \
+       examples-install        \
+       generate-server-key     \
+#endif SILC_DIST_SERVER
+#ifdef SILC_DIST_TOOLKIT
+       toolkit-install         \
+#endif SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_SIM
+       sim-install
+#endif SILC_DIST_SIM
+
+include $(top_srcdir)/Makefile.defines.in
 
-if SILC_DIST_CLIENT
-install-data-hook: install-dirs-client sim-install doc-install-client etc-install-client
-else
-if SILC_DIST_TOOLKIT
-install-data-hook: install-dirs-client install-dirs-server sim-install doc-install-client doc-install-server toolkit-install examples-install etc-install-client etc-install-server
-else
-install-data-hook: install-dirs-server sim-install doc-install-server examples-install etc-install-server generate-server-key
-endif
-endif
+#endif SILC_DIST_SILC
similarity index 78%
rename from Makefile.defines.pre
rename to Makefile.defines.in
index 192ff0f58b809f909f757f18226915a00e2430f4..926a3035c61d8914db549e7e75a5313e135b85c1 100644 (file)
 #
 INCLUDES = $(ADD_INCLUDES) $(SILC_CFLAGS) -DHAVE_SILCDEFS_H \
        -I$(srcdir) -I$(top_srcdir) \
-       -I$(silc_top_srcdir) \
-       -I$(silc_top_srcdir)/lib/silccore \
-       -I$(silc_top_srcdir)/lib/silccrypt \
-        -I$(silc_top_srcdir)/lib/silcmath \
-        -I$(silc_top_srcdir)/lib/silcmath/mpi \
-       -I$(silc_top_srcdir)/lib/silcske \
-       -I$(silc_top_srcdir)/lib/silcsim \
-       -I$(silc_top_srcdir)/lib/silcutil \
-       -I$(silc_top_srcdir)/lib/silcsftp \
-       -I$(silc_top_srcdir)/lib/silcclient \
-       -I$(silc_top_srcdir)/lib/contrib \
-        -I$(silc_top_srcdir)/includes \
-        -I$(silc_top_srcdir)/doc
+       -I$(silc_top_srcdir) $(SILC_LIB_INCLUDES) \
+       -I$(silc_top_srcdir)/includes \
+       -I$(silc_top_srcdir)/doc
 
 #
 #includes-install: Makefile
similarity index 81%
rename from Makefile.defines_int.pre
rename to Makefile.defines_int.in
index 4c7f41450b428724a09584e8f56e35d597e2b305..3f82947145d85da14cd1cd305ef08bcceb3850f3 100644 (file)
@@ -37,6 +37,11 @@ SILC_COMMON_LIBS= @LIBS@ -L$(silc_top_srcdir)/lib -lsilc
 #
 SILC_CFLAGS=@CFLAGS@
 
+#
+# SILC Library includes
+#
+SILC_LIB_INCLUDES=@SILC_LIB_INCLUDES@
+
 #
 # Installation defines
 #
@@ -45,3 +50,9 @@ silc_modulesdir=@MODULESDIR@
 silc_helpdir=@HELPDIR@
 silc_docdir=@DOCDIR@
 silc_logsdir=@LOGSDIR@
+etcdir = $(DESTDIR)$(silc_etcdir)
+modulesdir = $(DESTDIR)$(silc_modulesdir)
+helpdir = $(DESTDIR)$(silc_helpdir)
+docdir = $(DESTDIR)$(silc_docdir)
+logsdir = $(DESTDIR)$(silc_logsdir)
+mandir = $(DESTDIR)@mandir@
index e7568ead1ca31985c33708f802e9e21d0c4fbb70..4672367dcada6f6fd79df060360a7d35a405a7dd 100644 (file)
@@ -164,18 +164,20 @@ Following directories currently exist in SILC source tree.
 Howto Compile SILC Source Tree
 ==============================
 
-After checkout from CVS the SILC source tree must be prepared for 
-configuration and compilation.  To compile the source tree, give,
+To be able to prepare the CVS tree for configuration and compilation
+Autodist must be installed into the system.  You can download the latest
+version of Autodist from: 
 
-       ./prepare
+       http://silcnet.org/software/download/autodist/
+
+To prepare the CVS source tree for configuration and compilation, give:
+
+       autodist
        ./configure --enable-debug
        make
 
-The ./prepare script is included in to the source tree and it never
-appears in public distribution.  The script prepares the source tree
-by creating configuration scripts and Makefiles.  The prepare must be
-run every time you make some changes to configuration scripts (however,
-making changes to Makefile.am's does not require running ./prepare).
+The autodist must be run every time you make some changes to configuration 
+scripts.
 
 As a developer you should read the ./configure script's help by
 giving ./configure --help and study all of its different options.  Also,
@@ -197,31 +199,31 @@ like "*server*,*rng*" to match all functions, and filenames that has
 can freely define regural expressions as debug string.
 
 
-Howto Clean SILC Source Tree
-============================
-
-To entirely clear the source tree to the state after it was checked out
-from CVS, give,
-
-       ./prepare-clean
-
-This calls `make distclean' plus removes automatically generated files
-by hand.  It also removes *.log files. However, it will not remove
-any other files you might have created.
-
-
 Makefiles and configuration files
 =================================
 
-Developers should never directly write a Makefile.  All Makefiles are
-always automatically generated by ./prepare and later by ./configure
-scripts.  Instead, developers must write Makefile.am files.  There
-are plenty of examples what they should look like.  If you change
-Makefile.am during development you don't have to run ./prepare, just
-run normal make.
-
-Configuration files are the files that ./prepare automatically generates
-and what will be included into public distribution.  ./prepare creates
-for example the ./configure script that is not commited to the CVS.
-`configure.in' is the file that developers must edit to change ./configure
-script.  After changing one must run  ./prepare.
+Developers should never directly write a Makefile.  All Makefiles are 
+always automatically generated by autodist and later by ./configure 
+scripts.  Instead, developers must write Makefile.ad files or Makefile.am 
+files.  If the Makefile needs to include any distdefs (SILC_DIST_XXX), 
+then Makefile.ad (.ad stands for autodist) must be written.  If the 
+Makefile is generic (common to all distributions) then Makefile.am may be 
+written.  Note that distdefs MUST NOT be used in Makefile.am files, as the 
+autodist will modify them.  See the source tree for examples.  If you 
+change Makefile.ad files, the autodist must be rerun.
+
+The autodist also creates the configure.ac script from which the autoconf 
+then creates the ./configure script.  All changes to configure must 
+always be done into the configure.ad scripts.  All changes made to 
+configure.ac will be lost.  The autodist distdefs may also be used in 
+configure.ad files.  It is also possible to write more than one 
+configure.ad in the source tree.  All configure.ad fragments will be 
+collected from the source tree by autodist and combined into one 
+configure.ac scripts.  After making changes to configure.ad files the 
+autodist must be rerun.
+
+The distdefs are defined in the corresponding distributions.  All 
+distributions live in distdir/ directory.  The distdefs can be used in any 
+file in the source tree, but mainly they are used in Makefile.ad, 
+configure.ad and source and headers files.  See autodist documentation for 
+more information how to use distdefs.
diff --git a/README.DIST b/README.DIST
new file mode 100644 (file)
index 0000000..e5264ef
--- /dev/null
@@ -0,0 +1,112 @@
+How to create SILC distributions
+================================
+
+This document describes how to prepare SILC distributions in SILC source
+tree and how to package distributions for releasing.  This also defines
+the procedure what one should do when distribution is created for
+releasing.
+
+
+The 'distributions' file
+========================
+
+The 'distributions' file descibres all distributions that can be created 
+from the SILC CVS source tree.  You should read that file if you want to 
+learn how to create new distributions.  The file already defines the main 
+distributions that can be created from the soure tree.  These are the 
+'client', 'server' and 'toolkit' distributions.
+
+
+Preparing distribution
+======================
+
+The SILC CVS source tree must be prepared before it can be configured, 
+compiled and packaged.  The ./prepare script is used to prepare 
+distribution for configuration, compilation and packaging.  To prepare a 
+specific distribution with specific version, give command:
+
+       autodist <name> <version>
+
+Where the <name> is the distribution name.  It is one of the distributions 
+that was defined in distdir/ directory.  The <version> is the version of 
+the distribution that will be prepared.  The version format is 
+major.minor.build, for example 0.9.10.  Example:
+
+       autodist client 0.9.15
+
+This prepares 'client' distribution of version 0.9.15.  The package will 
+have the version 0.9.15 automatically.
+
+
+Configuring and compiling the distribution
+==========================================
+
+When you prepare the distribution for releasing you should configure the 
+distribution without any specific configuration options, hence just give 
+the command:
+
+       ./configure
+
+To compile the distribution, give command:
+
+       make
+
+If you want you can clear the environment first with make clean command, 
+but this is not necessary.
+
+
+Packaging the distribution
+==========================
+
+After the distribution is prepared, configured and compiled it can be 
+packaged with the following commands:
+
+       make -C doc dist-hook
+       makedist --bzip2
+
+The 'makedist --bzip2' creates the default 'tar.gz' and 'tar.bz2' 
+distribution.
+
+NOTE:  Before giving this command, make sure that you do not have any of 
+the tests in the SILC source tree compiled.  If they are the binaries
+will be included in the distribution which is not allowed.  The tests are 
+always located in the tests/ directory, for example lib/silccore/tests/.
+The tests are not compiled by default, but if you compiled them by 
+yourself make sure you make clean them before creating the distribution.
+
+NOTE:  Same thing must be assured for silcer/ and tutorial/ sub
+directories.  Make sure they are not compiled and does not include any
+extra files.  If you haven't compiled them after the CVS checkout, they do
+not include any extra files.
+
+NOTE for 'toolkit' distribution:  Before giving make dist the following
+must be done:
+
+       go to util/robodoc/
+       give ./configure;make to compile robodoc
+       go to doc/
+       give make toolkit-ref-html
+
+This then creates the Toolkit reference manual.  After this the toolkit 
+distribution can be packaged.
+
+
+Before releasing the distribution
+=================================
+
+Before releasing the distribution the created distribution must be tagged 
+in the CVS so that it can be checkout at a later time, if needed.  The tag 
+format is as follows:
+
+       silc_<name>_<version>
+
+Where <name> is the distribution name and <version> is the version of the 
+distribution in following format: major_minor_build, for example 0_9_10.  
+Example:
+
+       silc_client_0_9_15
+
+To tag the distribution go to the root of the SILC CVS source tree and 
+give, for example, command:
+
+       cvs tag silc_client_0_9_15
diff --git a/TODO b/TODO
index 416a3cf15cc1344ccdf0f98fcf948d344ea144b8..e1c30b328f58a8ef9a9a301eb2113f60a1b252a8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,31 +1,47 @@
-TODO for Irssi SILC Client 1.0
-==============================
+TODO for SILC Client 1.0 branch
+===============================
 
- o Testing - See test plan:
-     http://silcnet.org/docs/silc-client-1.0-test.pdf
-     http://silcnet.org/docs/silc-client-1.0-test.ps
+ o Bugs reported on the mailing list that will be fixed eventually.
+   The numbers are arbitrary and assigned by me (c0ffee), bugs in
+   parentheses are fixed.
+
+   (#1    Ignore ALL doesn't ignore target using /me)
+   #2    specification of the silc network
+   (#3    expired private key dialogue doesn't work)
+   #4    silc client allows setting non-utf8 topics
+   #5    SILC-client displaying wrong totals with /names
 
 
 TODO for SILC Server 1.0
 ========================
 
+ o BUG: silc_idlist_del_client had been called but sock->user_data remained
+   and pointed to invalid pointer.  Where it was called is not known.
+
+ o Basic UTF-8 stringprep profile that makes sure UTF-8 strings are
+   as defined in spec-08 section 3.13.
+
+ o Server sometimes connects more than once to router and keeps
+   connecting even though connection exists.
+
  o Testing
 
 
 TODO/bugs In SILC Libraries
 ===========================
 
- o Test cases for all cryptographic primitive in lib/silccrypt/
-
  o Test cases for all payload encoding and decoding routins in lib/silccore/
 
  o Test cases for math library routines in lib/silcmath/
 
+ o Implement new version of SFTP protocol (missing versions 4 and 5, we
+   have version 3).
+
 
 TODO in Toolkit Documentation
 =============================
 
-Stuff that needs to be done in order to complete the Tooolkit Reference
+Stuff that needs to be done in order to complete the Toolkit Reference
 Manual (Do these to 0.9.x).
 
  o Write "Programming with Toolkit" document, describing how to build
diff --git a/acconfig.h.pre b/acconfig.h.pre
deleted file mode 100644 (file)
index ca82e2c..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Name of the package. */
-#undef PACKAGE
-
-/* Version of the package. */
-#undef VERSION
-
-/* Default configuration file */
-#undef SILC_SERVER_CONFIG_FILE
-
-/* Multi-thread support */
-#undef SILC_THREADS
-
-/* These can be defined only on other than Win32 systems */
-#ifndef SILC_WIN32
-
-/* Debugging */
-#undef SILC_DEBUG
-#undef SILC_STACKTRACE
-
-/* Multi-thread support */
-#undef SILC_HAVE_PTHREAD
-
-/* IPv6 Support */
-#undef HAVE_IPV6
-
-#endif /* SILC_WIN32 */
-
-/* Default paths */
-#undef SILC_ETCDIR
-#undef SILC_HELPDIR
-#undef SILC_DOCDIR
-#undef SILC_MODULESDIR
-#undef SILC_LOGSDIR
-
-/* SIM (SILC Module) support */
-#undef SILC_SIM
-#undef HAVE_RTLD_NOW
-#undef HAVE_RTLD_LAZY
-
-/* MP library */
-#undef SILC_MP_GMP
-#undef SILC_MP_NSS_MPI
-
-/* Redefs for SOCKS5 library */
-/* macros/curses checks */
-#undef HAS_CURSES
-#undef USE_SUNOS_CURSES
-#undef USE_BSD_CURSES
-#undef USE_SYSV_CURSES
-#undef USE_NCURSES
-#undef NO_COLOR_CURSES
-#undef SCO_FLAVOR
-
-#undef SOCKS
-#undef SOCKS5
-#undef Rconnect
-#undef Rgetsockname
-#undef Rgetpeername
-#undef Rbind
-#undef Raccept  
-#undef Rlisten
-#undef Rselect
-#undef Rrecvfrom
-#undef Rsendto
-#undef Rrecv
-#undef Rsend
-#undef Rread
-#undef Rwrite
-#undef Rrresvport
-#undef Rshutdown
-#undef Rlisten
-#undef Rclose
-#undef Rdup
-#undef Rdup2
-#undef Rfclose
-#undef Rgethostbyname
-
-/* Native WIN32 compilation (-mno-cygwin GCC option) under cygwin, though
-   the code compiles with any native WIN32 compiler. */
-#undef SILC_WIN32
-
-/* SILC distribution definitions (leave this at the end of file) */
diff --git a/apps/Makefile.ad b/apps/Makefile.ad
new file mode 100644 (file)
index 0000000..0a01a55
--- /dev/null
@@ -0,0 +1,23 @@
+#
+#  Makefile.ad
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
+
+SUBDIRS =      \
+#ifdef SILC_DIST_AUTODIST
+       autodist
+#endif SILC_DIST_AUTODIST
diff --git a/apps/autodist/AUTHORS b/apps/autodist/AUTHORS
new file mode 100644 (file)
index 0000000..99141c0
--- /dev/null
@@ -0,0 +1,3 @@
+Authors of SILC Autodist.
+
+Pekka Riikonen <priikone@iki.fi>
diff --git a/apps/autodist/COPYING b/apps/autodist/COPYING
new file mode 100644 (file)
index 0000000..5329321
--- /dev/null
@@ -0,0 +1,25 @@
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+   3. The name of the author may not be used to endorse or promote
+      products derived from this software without specific prior written
+      permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/apps/autodist/INSTALL b/apps/autodist/INSTALL
new file mode 100644 (file)
index 0000000..56b077d
--- /dev/null
@@ -0,0 +1,236 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.  If you're
+     using `csh' on an old version of System V, you might need to type
+     `sh ./configure' instead to prevent `csh' from trying to execute
+     `configure' itself.
+
+     Running `configure' takes awhile.  While running, it prints some
+     messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory.  After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc.  You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+give `configure' the option `--exec-prefix=PREFIX', the package will
+use PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the `--target=TYPE' option to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).  Here is a another example:
+
+     /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/apps/autodist/Makefile.am b/apps/autodist/Makefile.am
new file mode 100644 (file)
index 0000000..c9d8c9a
--- /dev/null
@@ -0,0 +1,49 @@
+#
+#  Makefile.am
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
+
+SUBDIRS = . doc tests
+
+AUTODIST_SOURCE = autodist.in makedist.in
+bin_SCRIPTS = autodist makedist
+
+autodistdir = @AUTODISTDIR@
+autodist_DATA = autodist.conf default COPYING
+
+CLEANFILES = $(bin_SCRIPTS)
+
+APIVERSION = @APIVERSION@
+# Install versioned links.
+install-exec-hook:
+       @for i in $(bin_SCRIPTS); do                                    \
+         f="`echo $$i | sed '$(transform)'`";                          \
+         fv="$$f-$(APIVERSION)";                                       \
+         rm -f $(DESTDIR)$(bindir)/$$fv;                               \
+         chmod +x $(DESTDIR)$(bindir)/$$f;                             \
+         chmod a-w $(DESTDIR)$(bindir)/$$f;                            \
+         ln $(DESTDIR)$(bindir)/$$f $(DESTDIR)$(bindir)/$$fv;          \
+       done
+
+uninstall-hook:
+       @for i in $(bin_SCRIPTS); do                                    \
+         f="`echo $$i|sed '$(transform)'`";                            \
+         fv="$$f-$(APIVERSION)";                                       \
+         rm -f $(DESTDIR)$(bindir)/$$fv;                               \
+        done
+
+EXTRA_DIST = $(AUTODIST_SOURCE) default autodist.conf
diff --git a/apps/autodist/README b/apps/autodist/README
new file mode 100644 (file)
index 0000000..e954599
--- /dev/null
@@ -0,0 +1,49 @@
+Autodist
+
+The Autodist is a source distribution management system that allows 
+powerful mechanisms to define what is included in and excluded from a 
+distribution, and what license the distribution is released under.  It is 
+also used to create the actual distribution source packages.  Autodist 
+allows distribution management in file, directory and file content level.  
+Different distributions may include different portions of files, for 
+example, excluding certain features from certain distributions.  It is 
+always guaranteed that anything not defined for the distribution, is 
+removed automatically (files, file content, directories), thus ensuring 
+that nothing is accidentally included in the distribution.
+
+Autodist is closely related to the Autoconf and Automake tools, and 
+complements the features Autoconf and Automake provides.  It is especially 
+targeted into circumstances where multiple distributions are created from 
+one source tree.  The Autoconf and Automake environment is mainly designed 
+for one application per one source tree situations.  Autodist provides 
+mechanisms to create all kinds of distributions that can be created from 
+one source tree.  To be able to use Autodist, the Autoconf and Automake 
+must be installed into the system.
+
+The motivation behind Autodist stems from need to be able to create 
+multiple distributions from one large source tree in a precise and 
+controllable manner.  The Autoconf and Automake provides mere basic 
+control what is included in and excluded from distributions and how the 
+distributions are created.  They also do not provide mechanism to define 
+different licensing conditions for different distributions, or changing 
+the license automatically for different user or customer purposes.  Many 
+large software projects, companies and corporations have commonly been 
+using Autoconf and Automake tools, but have had the need to create their 
+own ad-hoc mechanisms to control distribution creation.  The Autodist 
+attempts to provide a tool that any size software project or company can 
+effectively use to manage their distributions.
+
+Autodist is not a binary packaging system.  It is specificly used to 
+create source distributions.  A binary packaging system, however can be 
+hooked to the distribution creation process, if needed.
+
+Read the INSTALL file on how to install the Autodist.  Refer info pages 
+for Autodist documentation by giving 'info autodist'.  Mail suggestions 
+and/or patches to autodist@silcnet.org, and bugs to 
+autodist-bugs@silcnet.org.  Please, always include the Autodist version 
+number to your email.  Give 'autodist --version' to get version.
+
+Autodist was originally written for the SILC Project (Secure Internet Live 
+Conferencing), which needed controlled mechanism to create several 
+distinct distributions from one source tree.
+
diff --git a/apps/autodist/autodist.conf b/apps/autodist/autodist.conf
new file mode 100644 (file)
index 0000000..4748b0e
--- /dev/null
@@ -0,0 +1,49 @@
+# Autodist configuration file
+
+# By default distdef prefix is '_DIST_'.  To add your own prefix set the
+# prefix here.  NOTE: Remember to change all 'define' directives in
+# distributions to use the new prefix if you change it.  Example:
+#
+# DISTPREFIX="SILC"
+#
+# Will set the distdef prefix as 'SILC_DIST_'.
+# 
+DISTPREFIX=""
+
+# The distdef header will be created by the Autodist.  It need to be included
+# in the source code in order for the preprocessor to respect distdef 
+# conditionals in source code.  Example:
+#
+# DISTDEFS="include/distdefs.h"
+#
+DISTDEFS="distdefs.h"
+
+# Location of the aclocal tool.  If this is omitted the Autodist will not
+# run aclocal.  User need to run it manually then.
+#
+ACLOCAL="aclocal"
+
+# Location of the autoheader tool.  If this is omitted the Autodist will not
+# run autoheader.  User need to run it manually then.
+#
+AUTOHEADER="autoheader"
+
+# Location of the autoconf tool.  If this is omitted the Autodist will not
+# run autoconf.  User need to run it manually then.
+#
+AUTOCONF="autoconf"
+
+# Location of the automake tool.  If this is omitted the Autodist will not
+# run automake.  User need to run it manually then.
+#
+AUTOMAKE="automake -a"
+
+# Location of the libtoolize tool.  This option should be omitted if your
+# source tree does not use libtool.
+#
+LIBTOOLIZE="libtoolize --automake --copy"
+
+# Location of the make program.  This must be specified in order to be 
+# able to create distributions.
+#
+MAKE="make"
diff --git a/apps/autodist/autodist.in b/apps/autodist/autodist.in
new file mode 100755 (executable)
index 0000000..27e6c22
--- /dev/null
@@ -0,0 +1,1600 @@
+#!/bin/sh
+#
+# Author: Pekka Riikonen <priikone@silcnet.org>
+#
+# Copyright (C) 2005 Pekka Riikonen
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#   1. Redistributions of source code must retain the above copyright
+#      notice, this list of conditions and the following disclaimer.
+#   2. Redistributions in binary form must reproduce the above copyright
+#      notice, this list of conditions and the following disclaimer in the
+#      documentation and/or other materials provided with the distribution.
+#   3. The name of the author may not be used to endorse or promote
+#      products derived from this software without specific prior written
+#      permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+###############################################################################
+# Global variables
+
+# Packaging and compressing
+ad_gzip=true
+ad_bzip2=false
+ad_compress=false
+ad_zip=false
+
+# Distribution subdirectory
+distdir="distdir"
+am_distdir=
+
+# This current distribution
+distribution=default
+distfile=$distribution
+dist_version=0.0
+package=
+bug_report=
+
+# All inherited distributions in this distribution
+inherits=
+
+# All distribution defines for this distribution
+distdefs=
+
+# All distribution undefines for this distribution
+undistdefs=
+
+# All distribution options
+options=
+opt_template=false
+opt_no_dist=false
+opt_no_inherit=false
+
+# All includes
+includes=
+
+# All excludes
+excludes=
+
+# All noprocesses
+noprocess=
+
+# All pre, post pre-dist and post-dist hooks
+pre_hooks=
+post_hooks=
+pre_dist_hooks=
+post_dist_hooks=
+
+# Distribution license and license header
+license=
+licenseh=
+
+# Whether to output ad_debug information
+debug=false
+
+# Autodist version
+ver=@VERSION@
+
+###############################################################################
+# Configuration file
+if test -f "$distdir/autodist.conf"; then
+  . $distdir/autodist.conf
+fi
+
+DP=$DISTPREFIX
+
+
+###############################################################################
+# Functions
+
+#
+# Print out debug information if debugging is enabled.  To enable debugging
+# set the global variable "debug" to true value.
+#
+# Arguments: ad_debug <ad_debug string>
+#
+ad_debug()
+{
+  if test x$debug = xtrue; then
+    set -f
+    echo autodist: $1
+    set +f
+  fi
+}
+
+#
+# Prints out error message and exits the script.
+#
+# Arguments: ad_fatal <error message>
+#
+ad_fatal()
+{
+  set -f
+  echo autodist: error: $1
+  set +f
+  exit 1
+}
+
+#
+# Prints out warning message
+#
+# Arguments: ad_warning <warning message>
+#
+ad_warning()
+{
+  set -f
+  echo autodist: warning: $1
+  set +f
+}
+
+#
+# Initializes the Autodist environment, creates default distribution
+# directory, and default distribution.
+#
+# Arguments: ad_initialize
+#
+ad_initialize()
+{
+  ad_debug ">ad_initialize"
+
+  # Create default distdir
+  if test '!' -f $distdir; then
+    mkdir -p $distdir
+  fi
+
+  # Create Autodist configuration file
+  if test -f @AUTODISTDIR@/autodist.conf; then
+    cp -p @AUTODISTDIR@/autodist.conf $distdir
+  fi
+
+  # Create default distribution
+  if test -f @AUTODISTDIR@/default; then
+    cp -p @AUTODISTDIR@/default $distdir
+  fi
+
+  ad_debug "<ad_initialize"
+}
+
+#
+# Creates the distdefs header file including defined distdefs
+#
+# Arguments: ad_create_distdefs_h
+#
+ad_create_distdefs_h()
+{
+  ad_debug ">ad_create_distdefs_h"
+
+  fname=$DISTDEFS
+  rm -f $fname
+  echo "/*" > $fname
+  echo "  Automatically generated by Autodist $ver.  Do not edit." >> $fname
+  echo >> $fname
+  echo "  Generated: `date` by `whoami`" >> $fname
+  echo "  Distribution: $distribution" >> $fname
+  echo "  License: $license" >> $fname
+  echo "*/" >> $fname
+  echo >> $fname
+  echo "#ifndef _"$DP"_DISTDEFS_H" >> $fname
+  echo "#define _"$DP"_DISTDEFS_H" >> $fname
+  echo >> $fname
+
+  for i in $distdefs
+  do
+    echo "#define $i 1" >>$fname
+  done
+
+  echo >> $fname
+  echo "#endif /* _"$DP"_DISTDEFS_H */" >> $fname
+
+  ad_debug "<ad_create_distdefs_h"
+}
+
+#
+# Creates the main configure script for the distribution.  This runs
+# the aclocal, autoheader and autoconf tools.
+#
+# Arguments: ad_make_configure
+#
+ad_make_configure()
+{
+  ad_debug ">ad_make_configure"
+  local run_autoconf=false
+
+  rm -f configure
+
+  if test "$ACLOCAL"; then
+    ad_debug "Running aclocal"
+    $ACLOCAL 1>/dev/null 2>/dev/null
+    if test $? != 0; then
+      ad_fatal "aclocal failed"
+    fi
+  fi
+
+  if test "$AUTOCONF"; then
+    ad_debug "Running autoconf"
+    $AUTOCONF
+    if test $? != 0; then
+      ad_fatal "autoconf failed"
+    fi
+    run_autoconf=true
+  fi
+
+  if test "$AUTOHEADER"; then
+    ad_debug "Running autoheader"
+    $AUTOHEADER
+    if test $? != 0; then
+      ad_fatal "autoheader failed"
+    fi
+  fi
+
+  if test "$LIBTOOLIZE"; then
+    ad_debug "Running libtoolize"
+    $LIBTOOLIZE
+    if test $? != 0; then
+      ad_fatal "libtoolize failed"
+    fi
+  fi
+
+  if test x$run_autoconf = xtrue; then
+    if test '!' -f configure; then
+      ad_fatal "creating configure script failed"
+    fi
+  fi
+
+  ad_debug "<ad_make_configure"
+}
+
+#
+# Creates the configure.ac script from the configure.ad fragments in
+# the source tree.  Takes the source configure file as argument which
+# is used to create the actual configure.ac.
+#
+# Arguments: ad_make_configure_ac <configure_ac_source>
+#
+ad_make_configure_ac()
+{
+  ad_debug ">ad_make_configure_ac: $1"
+
+  if test '!' -f $1; then
+    ad_fatal "The configure file '$1' does not exist"
+  fi
+
+  local check="`cat $1 | sed 's/^[     ]*//' | grep -v "^#" | grep -e "AD_INIT"`"
+  if test -z $check; then
+    rm -f configure.ad.cfs
+    rm -f $fname $fname.tmp
+    ad_fatal "The 'AD_INIT' macro has not been set in configure.ac"
+  fi
+
+  rm -f configure.ac configure.ad.cfs
+
+  cfs=`find . -name configure\*\.ad`
+  for i in $cfs
+  do
+    if test "x$i" = "x$1"; then
+      continue
+    fi
+    ad_debug "including $i"
+    cat $i >> configure.ad.cfs
+  done
+
+  if test -f configure.ad.cfs; then
+    local check="`cat $1 | sed 's/^[   ]*//' | grep -v "^#" | grep -e "AD_INCLUDE_CONFIGURE"`"
+    if test -z $check; then
+      rm -f configure.ad.cfs
+      ad_warning "configure.ad fragments found but 'AD_INCLUDE_CONFIGURE' is not set"
+    fi
+  fi
+
+  # Header for configure.ac
+  fname="configure.tmp.ac"
+  echo "# Automatically generated by Autodist $ver.  Do not edit." > $fname
+  echo "# To make changes edit the $i file in the source tree." >> $fname
+  echo >> $fname
+  echo "# Source: $i" >> $fname
+  echo "# Generated: `date` by `whoami`" >> $fname
+  echo "# Distribution: $distribution" >> $fname
+  echo "# License: $license" >> $fname
+  echo >> $fname
+
+  ad_debug "creating configure.ac"
+  if test -f configure.ad.cfs; then
+    sed '/AD_INCLUDE_CONFIGURE/ r configure.ad.cfs' $1 > $fname.tmp
+    sed -e "/AD_INCLUDE_CONFIGURE/s///" $fname.tmp >> $fname
+    rm -f configure.ad.cfs $fname.tmp
+  else
+    cat $1 >> $fname.tmp
+  fi
+
+  # Process AD_INIT
+  sed -e "/AD_INIT/s//AC_INIT([$distribution], [$dist_version], [$bug_report], [$package])/" $fname > $fname.tmp
+
+  # Process for distribution
+  rm -f $fname
+  ad_process_file $fname.tmp $fname
+
+  # Remove any trailing backslashes
+  if test -f "$fname"; then
+    cat $fname | sed -e :a -e '/\\$/N; s/\\\n//; ta' > configure.ac
+  else
+    cp -p $fname.tmp configure.ac
+  fi
+  rm -f $fname $fname.tmp
+
+  ad_debug "<ad_make_configure_ac: $1"
+}
+
+#
+# Creates the Makefile.in files by running the automake tool.
+#
+# Arguments: ad_make_makefile_ins
+#
+ad_make_makefile_ins()
+{
+  ad_debug ">ad_make_makefile_ins"
+
+  if test "$AUTOMAKE"; then
+    ad_debug "Running automake"
+    $AUTOMAKE
+    if test $? != 0; then
+      ad_fatal "automake failed"
+    fi
+  fi
+
+  ad_debug "<ad_make_makefile_ins"
+}
+
+#
+# Creates the Makefile.am files from the Makefile.ad files in the
+# source tree.  This runs the distribution specific processing for the
+# Makefile.ad files.
+#
+# Arguments: ad_make_makefile_ams
+#
+ad_make_makefile_ams()
+{
+  ad_debug ">ad_make_makefile_ams"
+
+  files=`find . -name Makefile\.ad`
+  for ff in $files
+  do
+    fname=`echo $ff | sed s/\.ad//`
+
+    # Header for the Makefile.am
+    echo "# Automatically generated by Autodist $ver from Makefile.ad.  Do not edit." > $fname.am
+    echo "# To make changes edit the $ff file in the source tree." >> $fname.am
+    echo >> $fname.am
+    echo "# Source: $ff" >> $fname.am
+    echo "# Generated: `date` by `whoami`" >> $fname.am
+    echo "# Distribution: $distribution" >> $fname.am
+    echo "# License: $license" >> $fname.am
+    echo >> $fname.am
+
+    # Run the distribution processing for this Makefile.ad
+    ad_debug "Processing $ff to be $fname.am"
+    ad_process_file $ff $fname.tmp
+
+    # Remove any trailing backslashes
+    if test -f "$fname.tmp"; then
+      cat $fname.tmp | sed -e :a -e '/\\$/N; s/\\\n//; ta' >> $fname.am
+    else
+      cat $ff >> $fname.am
+    fi
+
+    rm -f $fname.tmp
+  done
+
+  ad_debug "<ad_make_makefile_ams"
+}
+
+#
+# Processes all files with .ad suffix, with exception of configure*.ad
+# and Makefile.ad files, for distribution from the source tree.
+#
+# Arguments: ad_process_ads
+#
+ad_process_ads()
+{
+  ad_debug ">ad_process_ads"
+
+  files=`find . -name \*\.ad \! -name configure\*\.ad \! -name Makefile\.ad`
+  for i in $files
+  do
+    fname=`echo $i | sed s/\.ad//`
+
+    # Header
+    echo "# Automatically generated by Autodist $ver.  Do not edit." > $fname
+    echo "# To make changes edit the $i file in the source tree." >> $fname
+    echo >> $fname
+    echo "# Source: $i" >> $fname
+    echo "# Generated: `date` by `whoami`" >> $fname
+    echo "# Distribution: $distribution" >> $fname
+    echo "# License: $license" >> $fname
+    echo >> $fname
+
+    # Run the distribution processing for this file
+    ad_debug "Processing $i to be $fname"
+    ad_process_file $i $fname
+  done
+
+  ad_debug "<ad_process_ads"
+}
+
+#
+# Includes files specified in the distribution for inclusion.  Used when
+# creating the distribution for packaging.
+#
+# include has the following format in distfile:
+#
+#   include <path> [<dest path>]
+#
+# If only source path, which may be file, directory or regular expression,
+# is specified the path will be same in distribution.  If the destination
+# path is specified that will be the new name and/or new location of the
+# source path.  This, in effect, is a cp utility with ability to create
+# directories if they do not exist.
+#
+# Arguments: ad_dist_includes <includeslist> <recursive>
+#
+ad_dist_includes()
+{
+  ad_debug ">ad_dist_includes: $1 $2"
+
+  # By default do not expand pathnames
+  set -f
+
+  # Add : separator at the end
+  local incs="`echo "$1" | sed 's/$/ : /'`"
+
+  src=
+  dst=
+  for i in $incs
+  do
+    if test "$i" = ":" && test -z "$src"; then
+      continue
+    fi
+    if test -z "$src"; then
+      src=$i
+      continue
+    fi
+    if test -z "$dst" && test "$i" != ":"; then
+      dst=$i
+    else
+      dst=$src
+    fi
+
+    ad_debug "Including $src into $dst"
+
+    if test -f "$src"; then
+      # Add file
+
+      if test "$src" = "$dst"; then
+        # Add to same location
+        d=`echo $src | sed 's,/[^/]*$,,'`
+        if test "$d" != "$src" && test "$d" != "." && \
+          test '!' -d $am_distdir/$d; then
+          mkdir -p $am_distdir/$d || exit 1
+        fi
+      else
+        # Add to different location
+        check=`echo "$dst" | sed 's/?//; s/*//; s/\[//; s/\]//'`
+        if test "$check" != "$dst"; then
+          ad_fatal "Invalid destination in 'include $src $dst'"
+        fi
+
+        d=`echo $dst | sed 's,/[^/]*$,,'`
+        if test "$d" != "$dst" && test "$d" != "." && \
+          test '!' -d $am_distdir/$d; then
+          mkdir -p $am_distdir/$d || exit 1
+        fi
+      fi
+
+      cp -p $src $am_distdir/$d || exit 1
+
+    elif test -d "$src"; then
+      # Add directory
+
+      if test "$src" = "$dst"; then
+       # Add to same location
+        d=`echo $src | sed 's,/[^/]*$,,'`
+        ds=`echo $src | sed 's/\/$//'`
+        if test "$ds" = "$d"; then
+          d=`echo $d | sed 's,/[^/]*$,,'`
+        fi
+        if test '!' -d $am_distdir/$d && test "$ds" != "$d"; then
+          mkdir -p $am_distdir/$d || exit 1
+        fi
+
+        cp -pR $src $am_distdir/$d || exit 1
+      else
+       # Add to different location
+        check=`echo "$dst" | sed 's/?//; s/*//; s/\[//; s/\]//'`
+        if test "$check" != "$dst"; then
+          ad_fatal "Invalid destination in 'include $src $dst'"
+        fi
+
+        d=`echo $dst | sed 's,/[^/]*$,,'`
+        ds=`echo $dst | sed 's/\/$//'`
+        if test "$ds" = "$d"; then
+          d=`echo $d | sed 's,/[^/]*$,,'`
+        fi
+        if test '!' -d $am_distdir/$d && test "$dst" != "$d"; then
+          mkdir -p $am_distdir/$d || exit 1
+        fi
+
+        cp -pR $src $am_distdir/$dst || exit 1
+      fi
+
+    elif test x$2 != xtrue; then
+      # We assume regular expression in filename
+      check=`echo "$src" | sed 's/?//; s/*//; s/\[//; s/\]//'`
+      if test "$check" == "$src"; then
+       if test '!' -a $src; then
+         ad_fatal "Including $src: No such file or directory"
+       fi
+       src=
+       dst=
+       continue
+      fi
+
+      # Recursively call this function with expanded pathnames.  The
+      # reason why we don't let sh by default expand patnames is that
+      # the include's destination is optional.  If sh expands by default
+      # we don't know the destination.  For this reason, we handle the
+      # expansion here ourselves.
+
+      # If src and dst are same, then expand the pathname as we'll copy
+      # matches to their own locations.
+      if test "$src" = "$dst"; then
+       # Expand pathnames, and format to our include format
+       set +f
+       srcs=`echo $src | sed -e 's/ / : /g' -e 's/^/ : /'` || exit 1
+       set -f
+      else
+       # Destination is new, and it has to be a directory.
+       check=`echo "$dst" | sed 's/?//; s/*//; s/\[//; s/\]//'`
+       if test "$check" != "$dst"; then
+         ad_fatal "Invalid destination in 'include $src $dst'"
+       fi
+
+       # Make sure dst has / at the end, as this must be a directory
+       dst=`echo $dst | sed 's/\/$//; s/$/\//'`
+
+       # Escape dst for sed
+       dste=`echo $dst | sed 's/\\//\\\\\//g'` || exit 1
+
+       # Expand pathnames, and format to our include format
+       set +f
+       srcs=`echo $src | sed -e "s/ / $dste : /g" \
+         -e 's/^/ : /' -e "s/$/ $dste/"` || exit 1
+       set -f
+      fi
+
+      # Include recursively
+      ad_dist_includes "$srcs" true
+
+    elif test '!' -a $src; then
+      ad_fatal "Including $src: No such file or directory"
+    fi
+
+    src=
+    dst=
+  done
+
+  set +f
+
+  ad_debug "<ad_dist_includes: $1 $2"
+}
+
+#
+# Excludes files specified in the distribution for exclusion.  Used when
+# creating the distribution for packaging.
+#
+# exclude has the following format in distfile:
+#
+#  exclude <path>
+#
+# The path may be file, directory or regular expression.
+#
+# Arguments: ad_dist_includes <excludelist>
+#
+ad_dist_excludes()
+{
+  ad_debug ">ad_dist_excludes: $1"
+
+  for i in $1
+  do
+    ad_debug "Excluding $i"
+    rm -rf $am_distdir/$i
+  done
+
+  ad_debug "<ad_dist_excludes: $1"
+}
+
+#
+# Processes the entire tree for distribution.  This inspects files other
+# than source and header files, with exception of any file with .ad
+# suffix, and performs distribution processing for the file.  The original
+# file is replaced with the processed file.  This function is used when
+# creating the distribution for packaging.
+#
+# Arguments: ad_process_tree <directory>
+#
+ad_process_tree()
+{
+  ad_debug ">ad_process_tree: $1"
+
+  # We take all files, other than *.ad, including source files, in case
+  # they use the non-C-compiler-friendly format of distdefs, which is
+  # possible.
+
+  files=`find $am_distdir \! -name \*\.ad`
+  files=`echo $files | sed 's/$am_distdir//'`
+
+  # Take away noprocess list
+  if test -f autodist.noprocess; then
+    files=`echo $files | sh autodist.noprocess` || exit 1
+  fi
+
+  for ff in $files
+  do
+    ad_process_file $ff $ff.tmp
+    if test -f $ff.tmp; then
+      rm -f $ff || exit 1
+      mv -f $ff.tmp $ff || exit 1
+    fi
+  done
+
+  ad_debug "<ad_process_tree: $1"
+}
+
+#
+# Processes the entire source tree for distribution.  This inspects files
+# in the source tree, with exception of any file with .ad suffix, and
+# performs distribution processing for the file.  The original file is
+# replaced with the processed file.  This function is used when creating
+# the distribution for packaging.
+#
+# Call this before ad_process_tree().
+#
+# Arguments: ad_process_source_tree <directory>
+#
+ad_process_source_tree()
+{
+  ad_debug ">ad_process_source_tree: $1"
+
+  # We take only C/C++ files since they use the C compiler friendly
+  # version of distdefs.  Other files are not assumed to use them.
+  files=`find $am_distdir \! -name \*\.ad \( \
+       -name \*\.[cC] -o \
+       -name \*\.[cC][cCpP] -o \
+       -name \*\.[cC][xX][xX] -o \
+       -name \*\.[cC][pP][pP] -o \
+       -name \*\.[cC]++ -o \
+       -name \*\.m -o \
+       -name \*\.[hH] -o \
+       -name \*\.hh \)`
+
+  # Take away noprocess list
+  if test -f autodist.noprocess; then
+    files=`echo $files | sh autodist.noprocess` || exit 1
+  fi
+
+  for ff in $files
+  do
+    ad_process_source_file $ff $ff.tmp
+    if test -f $ff.tmp; then
+      rm -f $ff || exit 1
+      mv -f $ff.tmp $ff || exit 1
+    fi
+  done
+
+  ad_debug "<ad_process_source_tree: $1"
+}
+
+#
+# Makes distribution sane, ala modtimes.  Since we modify the distribution
+# we need to make it sane after that.
+#
+# Arguments: ad_makedist_makesane
+#
+ad_makedist_makesane()
+{
+  ad_debug ">ad_makedist_makesane:"
+
+  # DO NOT change these order unless you know what you are doing.
+  if test -f $am_distdir/configure.ac; then
+    touch $am_distdir/configure.ac
+  fi
+
+  if test -f $am_distdir/aclocal.m4; then
+    touch $am_distdir/aclocal.m4
+  fi
+
+  if test '!' -f Makefile; then
+    ad_fatal "Makefile: No such file or directory"
+  fi
+
+  configh=`grep "^CONFIG_HEADER" Makefile | cut -d= -f2 | sed 's/^[ \t]//'`
+  touch $am_distdir/$configh.in 1>/dev/null 2>/dev/null
+
+  files=`find $am_distdir -name Makefile\.in`
+  for i in $files
+  do
+    touch $i
+  done
+
+  if test -f $am_distdir/configure; then
+    touch $am_distdir/configure
+  fi
+
+  if test -f $am_distdir/config.status; then
+    touch $am_distdir/config.status
+  fi
+
+  ad_debug "<ad_makedist_makesane:"
+}
+
+#
+# Creates distribution of the source tree.  All files in the distribution
+# will be processed and the distribution will be packaged.
+#
+# Arguments: ad_makedist
+#
+ad_makedist()
+{
+  ad_debug ">ad_makedist"
+
+  if test '!' -f autodist.dist; then
+    ad_fatal "Autodist has not been run yet to prepare source tree"
+  fi
+
+  if test -z $MAKE; then
+    ad_fatal "The MAKE variable is not set in autodist.conf"
+  fi
+
+  # Get distdir from Makefile
+  if test '!' -f Makefile; then
+    ad_fatal "The source tree is not configured, run ./configure first"
+  fi
+
+  # Parse the requested distribution
+  distribution=`cat autodist.dist | grep "dist:" | cut -d: -f2`
+  dist_version=`cat autodist.dist | grep "ver:" | cut -d: -f2`
+  ad_parse_distribution $distribution false
+  ad_process_distdefs
+  am_distdir="$package-$dist_version"
+
+  if test x$opt_no_dist = xtrue; then
+    ad_fatal "The '$distribution' distribution cannot be packaged"
+  fi
+
+  # Create distribution directory
+  ad_debug "Creating distribution directory $am_distdir"
+  $MAKE distdir || exit 1
+  chmod -R a+r $am_distdir
+
+  if test '!' -d $am_distdir; then
+    ad_fatal "Distribution directory $am_distdir not created"
+  fi
+
+  # Run pre-dist-hooks
+  ad_run_dist_hooks "$pre_dist_hooks"
+
+  # Run excludes
+  ad_dist_excludes "$excludes"
+
+  # Run includes
+  ad_dist_includes "$includes"
+
+  # Include specific license file if specified
+  if test "$license" != ""; then
+    cp -p $license $am_distdir/COPYING || exit 1
+  fi
+
+  # Process noprocesses
+  ad_process_noprocess
+
+  # Process source files
+  ad_debug "Process distribution source tree"
+  ad_process_source_tree $am_distdir
+
+  # Process non-source files
+  ad_debug "Process distribution tree"
+  ad_process_tree $am_distdir
+
+  # Run post-dist-hooks
+  ad_run_dist_hooks "$post_dist_hooks"
+
+  # Make distribution sane
+  ad_makedist_makesane
+
+  # Package
+  ad_debug "Packaging distribution"
+  tar chof $am_distdir.tar $am_distdir || exit 1
+
+  # Compress
+  ad_debug "Compressing distribution package"
+  if test x$ad_gzip = xtrue; then
+    gzip -9 -c $am_distdir.tar > $am_distdir.tar.gz || exit 1
+  fi
+  if test x$ad_bzip2 = xtrue; then
+    bzip2 -9 -c $am_distdir.tar > $am_distdir.tar.bz2 || exit 1
+  fi
+  if test x$ad_compress = xtrue; then
+    compress -c $am_distdir.tar > $am_distdir.tar.Z || exit 1
+  fi
+  if test x$ad_zip = xtrue; then
+    rm -f $am_distdir.zip
+    zip -rq $am_distdir.zip $am_distdir || exit 1
+  fi
+  rm -f $am_distdir.tar
+
+  # Cleanup
+  rm -rf $am_distdir
+  rm -f autodist.noprocess
+
+  ad_debug "<ad_makedist"
+}
+
+#
+# Handles distribution options.
+#
+# option has the following format in distfile:
+#
+#   option <option>
+#
+# Following options are supported:
+#
+#   template
+#   no-dist
+#   no-inherit
+#
+# Arguments: ad_handle_options <options>
+#
+ad_handle_options()
+{
+  ad_debug ">ad_handle_options: $1"
+
+  for i in $1
+  do
+    if test "$i" = "template"; then
+      opt_template=true
+      continue
+    elif test "$i" = "no-dist"; then
+      opt_no_dist=true
+      continue
+    elif test "$i" = "no-inherit"; then
+      opt_no_inherit=true
+      continue
+    fi
+  done
+
+  ad_debug "<ad_handle_options: $1"
+}
+
+#
+# Clears set options
+#
+# Arguments: ad_clear_options
+#
+ad_clear_options()
+{
+  ad_debug ">ad_clear_options"
+  opt_template=false
+  opt_no_dist=false
+  opt_no_inherit=false
+  ad_debug "<ad_clear_options"
+}
+
+#
+# Parses the distribution.  Gets all distribution defines from the
+# distribution.  This also expands all inherited distributions recursively
+# to get all inherited distribution defines.  From inherited distributions
+# their name and package name is not inherited.
+#
+# Arguments: ad_parse_distribution <distribution name> <inherit>
+#
+ad_parse_distribution()
+{
+  ad_debug ">ad_parse_distribution: $1 $2"
+
+  if test '!' -f $distdir/$1; then
+    ad_fatal "Distribution '$1' is not declared"
+  fi
+
+  # Get inherited
+  local inhs=`cat $distdir/$1 | sed 's/^[      ]*//' | grep -v "^#" \
+    | grep "inherit " | cut -d' ' -f2 | sort | uniq`
+
+  # Get distdefs
+  local defs=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+   | grep "define " | cut -d' ' -f2 | sort | uniq`
+
+  if test "$inhs" = "" && test "$defs" = ""; then
+    ad_fatal "Distribution '$1' does not define anything"
+  fi
+
+  # Get undefined distdefs
+  local undefs=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+   | grep "undef " | cut -d' ' -f2 | sort | uniq`
+
+  # Get includes
+  local incs=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+    | grep "include " | sed 's/include / : /'`
+
+  # Get excludes
+  local excs=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+    | grep "exclude " | cut -d' ' -f2- | sort | uniq`
+
+  # Get noprocesses
+  local nops=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+    | grep "noprocess " | cut -d' ' -f2- | sort | uniq`
+
+  # Get options
+  local opts=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+    | grep "option " | cut -d' ' -f2- | sort | uniq`
+
+  # Check options
+  ad_handle_options "$opts"
+  if test x$2 = xtrue && test x$opt_no_inherit = xtrue; then
+    ad_fatal "Distribution '$1' cannot be inherited"
+  fi
+  if test x$2 = xfalse && test x$opt_template = xtrue; then
+    ad_fatal "Template distribution '$1' cannot be prepared or packaged"
+  fi
+
+  ad_debug "inherits=$inhs"
+  ad_debug "distdefs=$defs"
+  ad_debug "includes=$incs"
+  ad_debug "excludes=$excs"
+  ad_debug "noprocess=$nops"
+  ad_debug "undistdefs=$undefs"
+  ad_debug "options=$opts"
+
+  # Expand distdefs from inherited distributions
+  for i in $inhs
+  do
+    if test x$1 = x$i; then
+      ad_fatal "Infinite recursion detected.  Fix the '$distdir/$1' \
+            distribution to not have 'inherit $i' declared."
+    fi
+
+    if test '!' -f $distdir/$i; then
+      ad_fatal "Distribution '$i' is not declared (inherited from '$1')"
+    fi
+
+    ad_parse_distribution $i true
+    ad_clear_options
+  done
+
+  # Get license
+  license=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+    | grep "license " | cut -d' ' -f2`
+  licenseh=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+    | grep "license-header " | sed 's/license-header / : /'`
+
+  ad_debug "license=$license"
+  ad_debug "licenseh=$licenseh"
+
+  if test x$2 = xfalse; then
+    # Get distribution name
+    local dname=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+      | grep "name " | cut -d' ' -f2-`
+
+    if test "$dname"; then
+      distribution=$dname
+    fi
+
+    # Get distribution package name (optional)
+    local dpname=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+     | grep "package " | cut -d' ' -f2`
+
+    if test "$dpname"; then
+      package=$dpname
+    else
+      package=$distribution
+    fi
+
+    # Get Bug-report email address (optional)
+    local bugr=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+     | grep "bug-report " | cut -d' ' -f2-`
+
+    if test "$bugr"; then
+      bug_report=$bugr
+    fi
+
+    ad_debug "distribution=$distribution"
+    ad_debug "package=$package"
+    ad_debug "bug-report=$bug_report"
+
+    # Get hooks (optional)
+    local prh=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+     | grep "pre-hook " | cut -d' ' -f2-`
+    local poh=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+     | grep "post-hook " | cut -d' ' -f2-`
+    local prdh=`cat $distdir/$1 | sed 's/^[       ]*//' | grep -v "^#" \
+     | grep "pre-dist-hook " | sed 's/^[       ]*//' | cut -d' ' -f2-`
+    local podh=`cat $distdir/$1 | grep -v "^#" \
+     | grep "post-dist-hook " | sed 's/^[       ]*//' | cut -d' ' -f2-`
+
+    pre_hooks="$pre_hooks $prh"
+    post_hooks="$post_hooks $poh"
+    pre_dist_hooks="$pre_dist_hooks $prdh"
+    post_dist_hooks="$post_dist_hooks $podh"
+    options="$options $opts"
+
+    ad_handle_options "$options"
+    ad_debug "options=$options"
+  fi
+
+  # Return to caller
+  inherits="$inherits $inhs"
+  distdefs="$distdefs $defs"
+  includes="$includes $incs"
+  excludes="$excludes $excs"
+  noprocess="$noprocess $nops"
+  undistdefs="$undistdefs $undefs"
+
+  ad_debug "<ad_parse_distribution: $1 $2"
+}
+
+#
+# Processes parsed distdefs.  Removes duplicates, and undefined distdefs
+# from the distdefs.
+#
+# Arguments: ad_process_distdefs
+#
+ad_process_distdefs()
+{
+  ad_debug ">ad_process_distdefs"
+
+  # Remove all undefined distribution defines
+  for i in $undistdefs
+  do
+    ad_debug "undefining $i distdef"
+    distdefs=`echo $distdefs | sed s/$i//`
+  done
+
+  rm -f autodist.tmp.defs autodist.pre.hooks autodist.post.hooks
+  rm -f autodist.pre.dist.hooks autodist.post.dist.hooks
+
+  # Remove duplicate distdefs
+  for i in $distdefs
+  do
+    echo $i >>autodist.tmp.defs
+  done
+  distdefs=`cat autodist.tmp.defs | sort | uniq`
+  distdefs=`echo $distdefs`
+  rm -f autodist.tmp.defs
+
+  ad_debug "distdefs=$distdefs"
+
+  ad_debug "<ad_process_distdefs"
+}
+
+#
+# Processes for a license header change.
+#
+# Arguments: ad_process_license_header <scriptfile>
+#
+ad_process_license_header()
+{
+  ad_debug ">ad_process_license_header"
+
+  # Add : separator at the end
+  lics=`echo "$licenseh" | sed 's/$/ : /'`
+
+  src=
+  dst=
+  for i in $lics
+  do
+    if test "$i" = ":" && test -z "$src"; then
+      continue
+    fi
+    if test -z "$src"; then
+      src=$i
+      continue
+    fi
+    if test -z "$dst" && test "$i" != ":"; then
+      dst=$i
+    else
+      ad_fatal "Missing argument in 'license-header $src'"
+    fi
+
+    ad_debug "Replacing $src license with $dst license"
+
+    if test '!' -f $src; then
+      ad_fatal "License header $src: No such file or directory"
+    fi
+
+    if test '!' -f $dst; then
+      ad_fatal "License header $dst: No such file or directory"
+    fi
+
+    # Awk script to replace the license header
+    fl=`sed q $src | sed 's/\\//\\\\\//g' > autodist.lsrc` || exit 1
+    ll=`sed -n '$p' $src | sed 's/\\//\\\\\//g' > autodist.ldst` || exit 1
+    echo "/`cat autodist.lsrc`/,/`cat autodist.ldst`/ { FILE1=\"$src\"; FILE2=\"$dst\"; getline F1 < FILE1; getline F2 < FILE2; if (F1) sub(F1, F2); else { F1=\"\$\"; sub(F1, F2); } }" >> $1
+    rm -f autodist.lsrc autodist.ldst
+
+    src=
+    dst=
+  done
+
+  ad_debug "<ad_process_license_header"
+}
+
+#
+# Process specified noprocesses.  This is called during makedist.
+#
+# Arguments: ad_process_noprocess
+#
+ad_process_noprocess()
+{
+  ad_debug ">ad_process_noprocess"
+  local np=false
+
+  local n="sed "
+
+  for i in $noprocess
+  do
+    # Escape
+    ie=`echo $i | sed 's/\\//\\\\\//g'` || exit 1
+
+    n="$n -e 's/$am_distdir\\/$ie//'"
+    np=true
+  done
+
+  rm -f autodist.noprocess
+  if test x$np = xtrue; then
+    echo $n > autodist.noprocess || exit 1
+  fi
+
+  ad_debug "<ad_process_noprocess"
+}
+
+#
+# Process a file given as argument for the distribution.
+#
+# Arguments: ad_process_file <filepath> <dest_filepath>
+#
+ad_process_file()
+{
+  local found=false
+
+  # Process only regular files
+  if test '!' -f $1; then
+    return
+  fi
+
+  ad_debug ">ad_process_file: $1 $2"
+
+  local f="autodist.tmp.script"
+  rm -f $f
+
+  # If license header is provided, replace the license header in the file.
+  ad_process_license_header $f
+
+  ad_debug "Getting #ifdef's and #ifndef's"
+
+  # Get defined distribution defines
+  local defs=`awk "/^#ifdef "$DP"_DIST_|^#else "$DP"_DIST_/ { print; }" \
+    $1 |cut -d'*' -f2 |cut -d' ' -f2 | sort | uniq`
+
+  # Get explicitly not-defined distribution defines
+  local ndefs=`awk "/^#ifndef "$DP"_DIST_|^#else !"$DP"_DIST_/ { print; }" \
+    $1 |cut -d'*' -f2 |cut -d' ' -f2 | cut -d'!' -f2 | sort | uniq`
+
+  ad_debug "defs=$defs"
+  ad_debug "ndefs=$ndefs"
+
+  # Create the script to include and exclude stuff in the file according
+  # to the distribution defines
+
+  # ifdefs
+  ad_debug "processing ifdefs"
+  for d in $defs
+  do
+    found=false
+    for i in $distdefs
+    do
+      if test x$d = x$i; then
+        found=true
+        break
+      fi
+    done
+
+    # If distribution define was not found exclude those lines from the file.
+    # This also handles the #ifdef's #else (ie. #ifndef) branch.
+    if test x$found = xfalse; then
+      ad_debug "ifdef $d will be excluded (it is NOT defined)"
+      echo "/^#ifdef $d/,/^#else !$d|^#endif $d/ { next; }" >> $f
+    else
+      echo "/^#else !$d/,/^#endif $d/ { next; }" >> $f
+    fi
+  done
+
+  # ifndefs
+  ad_debug "processing ifndefs"
+  for d in $ndefs
+  do
+    found=false
+    for i in $distdefs
+    do
+      if test x$d = x$i; then
+        found=true
+        break
+      fi
+    done
+
+    # If distribution define was found exclude those lines from the file.
+    # This also handles the #ifndef's #else (ie. #ifdef) branch.
+    if test x$found = xtrue; then
+      ad_debug "ifndef $d will be excluded (it IS defined)"
+      echo "/^#ifndef $d/,/^#else $d|^#endif $d/ { next; }" >> $f
+    else
+      echo "/^#else $d/,/^#endif $d/ { next; }" >> $f
+    fi
+  done
+
+  # Now process the file with the script
+  if test -f $f; then
+
+    # Those distdef lines that remain in the file are removed to make
+    # the appearance prettier
+    echo "/^#ifdef "$DP"_DIST_|^#endif "$DP"_DIST_|^#else "$DP"_DIST_|^#else !"$DP"_DIST_|^#ifndef "$DP"_DIST_/ { next; }" >> $f
+    echo "{ print; }" >> $f
+
+    # Execute the script
+    cp -p $1 $2 || exit 1
+    awk -f $f $1 > $2 || exit 1
+  fi
+
+  rm -f $f
+
+  ad_debug "<ad_process_file: $1 $2"
+}
+
+#
+# Process a source file given as argument for the distribution.
+#
+# Arguments: ad_process_source_file <filepath> <dest_filepath>
+#
+ad_process_source_file()
+{
+  local found=false
+
+  # Process only regular files
+  if test '!' -f $1; then
+    return
+  fi
+
+  ad_debug ">ad_process_source_file: $1 $2"
+
+  local f="autodist.tmp.script"
+  rm -f $f
+
+  # If license header is provided, replace the license header in the file.
+  ad_process_license_header $f
+
+  ad_debug "Getting #ifdef's and #ifndef's"
+
+  # Get defined distribution defines
+  local defs=`awk '/^#ifdef SILC_DIST_|^#else \/\* SILC_DIST_/ { print; }' \
+    $1 |cut -d'*' -f2 |cut -d' ' -f2 | sort | uniq`
+
+  # Get explicitly not-defined distribution defines
+  local ndefs=`awk '/^#ifndef SILC_DIST_|^#else \/\* \!SILC_DIST_/ { print; }' \
+    $1 |cut -d'*' -f2 |cut -d' ' -f2 | cut -d'!' -f2 | sort | uniq`
+
+  ad_debug "defs=$defs ndefs=$ndefs"
+
+  # Create the script to include and exclude stuff in the file according
+  # to the distribution defines
+
+  # ifdefs
+  ad_debug "processing ifdefs"
+  for d in $defs
+  do
+    found=false
+    for i in $distdefs
+    do
+      if test x$d = x$i; then
+        found=true
+        break
+      fi
+    done
+
+    # If distribution define was not found exclude those lines from the file.
+    # This also handles the #ifdef's #else (ie. #ifndef) branch.
+    if test x$found = xfalse; then
+      ad_debug "ifdef $d will be excluded (it is NOT defined)"
+      echo "/^#ifdef $d/,/^#else \/\* \!$d|^#endif \/\* $d/ { next; }" >> $f
+    else
+      echo "/^#else \/\* \!$d/,/^#endif \/\* $d/ { next; }" >> $f
+    fi
+  done
+
+  # ifndefs
+  ad_debug "processing ifndefs"
+  for d in $ndefs
+  do
+    found=false
+    for i in $distdefs
+    do
+      if test x$d = x$i; then
+        found=true
+        break
+      fi
+    done
+
+    # If distribution define was found exclude those lines from the file.
+    # This also handles the #ifndef's #else (ie. #ifdef) branch.
+    if test x$found = xtrue; then
+      ad_debug "ifndef $d will be excluded (it IS defined)"
+      echo "/^#ifndef $d/,/^#else \/\* $d|^#endif \/\* $d/ { next; }" >> $f
+    else
+      echo "/^#else \/\* $d/,/^#endif \/\* $d/ { next; }" >> $f
+    fi
+  done
+
+  # Now process the file with the script
+  if test -f $f; then
+
+    # Those distdef lines that remain in the file are removed to make
+    # the appearance prettier
+    echo "/^#ifdef SILC_DIST_|^#endif \/\* SILC_DIST_|^#else \/\* SILC_DIST_|^#else \/\* \!SILC_DIST_|^#ifndef SILC_DIST_/ { next; }" >> $f
+    echo "{ print; }" >> $f
+
+    # Execute the script
+    cp -p $1 $2 || exit 1
+    awk -f $f $1 > $2 || exit 1
+  fi
+
+  rm -f $f
+
+  ad_debug "<ad_process_source_file: $1 $2"
+}
+
+#
+# Run hooks
+#
+# Arguments: ad_run_hooks <hooks>
+#
+ad_run_hooks()
+{
+  ad_debug ">ad_run_hooks: $1"
+
+  for i in $1
+  do
+    if test '!' -f $i; then
+      ad_fatal "Hook script $i does not exist"
+    fi
+    sh $i $distribution $dist_version $package || exit 1
+  done
+
+  ad_debug "<ad_run_hooks: $1"
+}
+
+#
+# Run dist hooks
+#
+# Arguments: ad_run_dist_hooks <hooks>
+#
+ad_run_dist_hooks()
+{
+  ad_debug ">ad_run_dist_hooks: $1"
+
+  for i in $1
+  do
+    if test '!' -f $i; then
+      ad_fatal "Dist hook script $i does not exist"
+    fi
+    sh $i $distribution $dist_version $package $am_distdir || exit 1
+  done
+
+  ad_debug "<ad_run_dist_hooks: $1"
+}
+
+###############################################################################
+# Autodist code
+
+usage="Usage: autodist [options] [distribution] [version]"
+help="\
+Autodist prepares source tree for configuration, compilation and
+distribution.  Prepares the source tree from the \`autodist.ad'
+configuration file.  Generates Automake.am files from Automake.ad
+files, configure.ac file from configure.ad file(s), generates the
+configure script by running Autoconf tool, and generates Makefile.in
+files by running Automake tool.
+
+Operation modes:
+  -h, --help                print this help, then exit
+  -V, --version             print version number, then exit
+  -v, --verbose             verbosely report processing
+  -d, --distdir <dir>       search distributions from <dir>
+  -s, --distdefs [<dist>]   print distribution defines of <dist>, then exit
+  -i, --init                initialize Autodist environment, create default
+                            distribution directory and distribution, then exit
+  -m, --makedist            create and package distribution
+      --gzip                create package compressed with gzip (default)
+      --bzip2               create also package compressed with bzip2
+      --compress            create also package compressed with compress
+      --zip                 create also package compressed with zip"
+
+#
+# Process command line arguments
+#
+while test $# -gt 0; do
+  case "${1}" in
+
+  -d |--distdir)
+    shift;
+    test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; }
+    distdir="${1}";
+    shift;;
+
+  --list)
+    exit 0;;
+
+  -s | --distdefs)
+    shift;
+    if test $# -eq 0; then
+      ad_parse_distribution $distribution false
+      echo "Distribution: ${distribution}" 1>&2;
+    else
+      ad_parse_distribution $1 false
+      echo "Distribution: ${1}" 1>&2;
+    fi
+    ad_process_distdefs
+    echo "Distdefs:" 1>&2;
+    echo "${distdefs}";
+    exit 0;;
+
+  -i | --init)
+    ad_initialize;
+    exit 0;;
+
+  -m | --makedist)
+    ad_makedist
+    exit 0;;
+
+  --gzip)
+    ad_gzip=true
+    shift;;
+
+  --bzip2)
+    ad_bzip2=true
+    shift;;
+
+  --compress)
+    ad_compress=true
+    shift;;
+
+  --zip)
+    ad_zip=true
+    shift;;
+
+  -v | --verbose)
+    debug=true
+    shift;;
+
+  -h | --help | --h*)
+    echo "${usage}" 1>&2;
+    echo 1>&2;
+    echo "${help}" 1>&2;
+    echo 1>&2;
+    exit 0;;
+
+  -V | --version)
+    echo "@PACKAGE@ (@PACKAGE_NAME@) $ver" 1>&2;
+    echo "Written by Pekka Riikonen" 1>&2;
+    echo 1>&2;
+    echo "Copyright (C) 2004 - 2005 SILC Project" 1>&2;
+    echo "\
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. " 1>&2;
+    exit 0;;
+
+  --)
+    shift;
+    break;;
+
+  -*)
+    echo "${usage}" 1>&2;
+    exit 1;;
+
+  *)
+    break;;
+
+  esac
+done
+
+#
+# Parse the requested distribution
+#
+if test $# != 0; then
+  distribution="${1}";
+  distfile=$distribution
+  shift
+fi
+ad_parse_distribution $distribution false
+ad_process_distdefs
+
+if test $# != 0; then
+  dist_version="${1}";
+fi
+
+ad_debug "Preparing source tree for configuration and compilation..."
+ad_debug "Preparing $distribution distribution version $dist_version"
+
+#
+# Create the distribution defines header file
+#
+if test "$DISTDEFS"; then
+  ad_create_distdefs_h
+else
+  ad_fatal "DISTDEFS not defined in $distdir/autodist.conf"
+fi
+
+#
+# Run pre-hooks
+#
+ad_run_hooks "$pre_hooks"
+
+#
+# Generate the Makefile.am files from Makefile.ad files
+#
+ad_make_makefile_ams
+
+#
+# Generate the configure.ac from configure.ad file(s)
+#
+ad_make_configure_ac ./configure.ad
+
+#
+# Generate configure script
+#
+ad_make_configure
+
+#
+# Generate Makefile.in files
+#
+ad_make_makefile_ins
+
+#
+# Process all files with .ad suffix for distribution processing
+#
+ad_process_ads
+
+#
+# Create autodist.dist
+#
+ad_debug "Creating autodist.dist"
+echo "dist:$distfile" > autodist.dist
+echo "ver:$dist_version" >> autodist.dist
+echo "$package-$dist_version" >> autodist.dist
+
+#
+# Run post-hooks
+#
+ad_run_hooks "$post_hooks"
+
+ad_debug "Done, now run ./configure and make."
+exit 0
diff --git a/apps/autodist/configure.ad b/apps/autodist/configure.ad
new file mode 100644 (file)
index 0000000..806ac54
--- /dev/null
@@ -0,0 +1,52 @@
+#ifdef SILC_DIST_AUTODIST
+#
+#  apps/autodist/configure.ad
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+# The APIVERSION is appended to the filename, to give versioned name.
+# The base version (X.Y) is taken.
+APIVERSION=`echo "$VERSION" | sed -e 's/^\([[0-9]]*\.[[0-9]]*[[a-z]]*\).*$/\1/'`
+AC_SUBST(APIVERSION)
+
+old_exec_prefix=$exec_prefix
+old_prefix=$prefix
+exec_prefix=$silc_prefix
+prefix=$silc_prefix
+
+# Path to the autodist in installed environment
+s_bindir=`eval echo $bindir`;s_bindir=`eval echo $s_bindir`
+AUTODIST=$s_bindir/autodist
+AC_SUBST(AUTODIST)
+
+# Path to the Autodist data
+s_datadir=`eval echo $datadir`;s_bindir=`eval echo $s_datadir`
+AUTODISTDIR=$s_datadir/autodist
+AC_SUBST(AUTODISTDIR)
+
+exec_prefix=$old_exec_prefix
+prefix=$old_prefix
+
+#
+# Makefile outputs
+#
+AC_CONFIG_FILES(
+apps/autodist/Makefile
+apps/autodist/autodist
+apps/autodist/makedist
+apps/autodist/doc/Makefile
+apps/autodist/tests/Makefile
+)
+#endif SILC_DIST_AUTODIST
diff --git a/apps/autodist/default b/apps/autodist/default
new file mode 100644 (file)
index 0000000..84cea7c
--- /dev/null
@@ -0,0 +1,10 @@
+# Default distribution
+#
+# NOTE: By default, this distribution cannot be packaged.  Take away the
+# 'no-dist option if you whish to use this as a normal distribution.
+#
+# If you add new distributions into distdir/ you may want to inherit them 
+# here.
+#
+option no-dist
+define _DIST_DEFAULT
diff --git a/apps/autodist/doc/Makefile.am b/apps/autodist/doc/Makefile.am
new file mode 100644 (file)
index 0000000..2ffb4b0
--- /dev/null
@@ -0,0 +1,19 @@
+#
+#  Makefile.am
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+info_TEXINFOS = autodist.texi
+autodist_TEXINFOS = fdl.texi
diff --git a/apps/autodist/doc/autodist.texi b/apps/autodist/doc/autodist.texi
new file mode 100644 (file)
index 0000000..870cc91
--- /dev/null
@@ -0,0 +1,1603 @@
+\input texinfo   @c -*-texinfo-*-
+@c %**start of header
+@setfilename autodist.info
+@settitle autodist
+@setchapternewpage off
+@c %**end of header
+
+@include version.texi
+
+@copying
+
+This manual is for SILC Autodist (version @value{VERSION},
+@value{UPDATED}), a program which is used to manage and create source
+distributions.
+
+Copyright @copyright{} 2004 - 2005 Pekka Riikonen, SILC Project
+
+@quotation
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the @acronym{GNU} Free Documentation License,
+Version 1.2 or any later version published by the Free Software
+Foundation; with no Invariant Sections, with the Front-Cover texts
+being ``A @acronym{GNU} Manual,'' and with the Back-Cover Texts as in
+(a) below.  A copy of the license is included in the section entitled
+``@acronym{GNU} Free Documentation License.''
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and
+modify this @acronym{GNU} Manual, like @acronym{GNU} software.  Copies
+published by the Free Software Foundation raise funds for
+@acronym{GNU} development.''
+@end quotation
+@end copying
+
+@dircategory Software development
+@direntry
+* autodist: (autodist).         Managing and creating source distributions.
+@end direntry
+
+@dircategory Individual utilities
+@direntry
+* makedist: (autodist)Invoking makedist.          Creating distribution
+@end direntry
+
+@titlepage
+@title SILC Autodist
+@subtitle For version @value{VERSION}, @value{UPDATED}
+@author Pekka Riikonen
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+@end titlepage
+
+@ifnottex
+@node Top
+@comment  node-name,  next,  previous,  up
+@top SILC Autodist
+
+@insertcopying
+
+@menu
+* Introduction::                Purpose of Autodist
+* Integrating Autodist::        Integrating Autodist into your project
+* Invoking Autodist::           Running Autodist
+* Examples::                    Examples using Autodist
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Introduction
+
+* Motivation::                  Reasons for using Autodist
+
+Integrating Autodist
+
+* Creating distdir::            Creating distributions directory
+* autodist.conf::               Configuring Autodist
+* Creating new distribution::   Adding new distribution
+* Distribution file format::    Detailed document for distfile format
+* configure.ad files::          configure script for creating configure.ac
+* Makefile.ad files::           Makefile.ad for creating Makefile.am
+* Other .ad files::             Other files with .ad suffix
+* Distdefines::                 Using distdefs in files
+
+Invoking Autodist
+
+* Preparing source tree::       Preparing source tree with Autodist
+* Creating distribution::       Creating distribution with Autodist
+
+Examples
+
+* Single distribution tree::    Single distribution example
+* Multiple distribution tree::  Multiple distributions example
+
+@end detailmenu
+@end menu
+
+@end ifnottex
+
+
+@node Introduction
+@chapter Introduction
+
+The Autodist is a source distribution management system that allows
+powerful mechanisms to define what is included in and excluded from a
+distribution, and what license the distribution is released under.  It is
+also used to create the actual distribution source packages.  Autodist
+allows distribution management in file, directory and file content level.
+Different distributions may include different portions of files, for
+example, excluding certain features from certain distributions.  It is
+always guaranteed that anything not defined for the distribution, is
+removed automatically (files, file content, directories), thus ensuring
+that nothing is accidentally included in the distribution.
+
+The Autodist creates 'Makefile.am' files from 'Makefile.ad' files and
+'configure.ac' file from one or more 'configure.ad' files.  Any other file
+ending with '.ad' suffix will also be processed.  The processed file will
+have the '.ad' suffix removed (@pxref{Preparing source tree, , , , }).
+Autodist also creates and packages the distribution using common GNU
+distribution creation process, specificly `make dist'.  Autodist, however,
+controls this process and during packaging phase the Autodist processes
+all files in the distribution (other than '*.ad' files, which has already
+been processed earlier by Autodist).  The resulted package is a processed
+source distribution package, processed according to the rules specified
+in the distribution file(s) (@pxref{Creating distribution, , , , }).
+
+Any file in the source tree may use distdefs (distribution defines (@pxref{Distdefines, , , , })) which are defined in the distributions.  When distribution
+is packaged only the files, directories and file content that is either
+outside of any distdef, or inside the defined distdefs will be included
+in the distribution.  Any other file, directory or content in the file
+will be removed.  It is guaranteed, if a file, a directory or a piece of
+file content is not inside a defined distdef it will not be delivered to
+the distribution.
+
+Any file, 'Makefile.am', 'configure.ac', or source file processed with
+Autodist is always compliant with the tools needed to process them.  All
+files can also be processed with the corresponding tools even before
+processing them with Autodist.  This makes it possible, for example, to
+compile sources before they have been processed, and undefined lines
+are removed.  The distdefs are respected in source files by the
+preprocessor.
+
+Autodist is not a binary packaging system.  It is specificly used to
+create source distributions.  A binary packaging system, however can be
+hooked to the distribution creation process, if needed.
+
+@menu
+* Motivation::                  Reasons for using Autodist
+@end menu
+
+
+@node Motivation
+@section Reasons for using Autodist
+
+Autodist is closely related to the Autoconf and Automake tools, and
+complements the features Autoconf and Automake provides.  It is especially
+targeted into circumstances where multiple distributions are created from
+one source tree.  The Autoconf and Automake environment is mainly designed
+for one distribution (one application) per one source tree situations.
+Autodist provides mechanisms to create all kinds of distributions that can
+be created from one source tree.  To be able to use Autodist, the Autoconf
+and Automake must be installed into the system (@pxref{Integrating Autodist, , , , }).
+Autoconf version must be at least 2.52g.
+
+Small software projects usually do very well with Autoconf and Automake
+and their distribution management features.  Often these projects do not
+need Autodist, though they can benefit from it.  However, if your software
+project is large, you need to create multiple distributions from one source
+tree, you have complex licensing terms for different distributions, you
+have different target users or customers that may require different
+feature set or licenses in different distributions, you have need to
+continue concurrent development in the main source tree and still be able
+to create stable distributions, and/or you have need to control file
+content in different distributions (to avoid distributing code or features
+that aren't supposed to be distributed, or to avoid leaking information
+to your competitors on what new features you are working on), then Autodist
+is a tool you may find usefull.
+
+The motivation behind Autodist stems from need to be able to create
+multiple distributions from one large source tree in a precise and
+controllable manner, and guarantee that anything that is not part of the
+distribution is removed from the distribution.  The Autoconf and Automake
+provides mere basic control what is included in and excluded from
+distributions and how the distributions are created.  They also do not
+provide mechanism to define different licensing conditions for different
+distributions, or changing the license automatically for different user
+or customer purposes.  Many large software projects, companies and
+corporations have commonly been using Autoconf and Automake tools, but
+have had the need to create their own ad-hoc mechanisms to control
+distribution creation.  The Autodist attempts to provide a tool that any
+size software project can effectively use to manage their distributions.
+
+Without a tool like Autodist, large software projects usually has to be
+split into separate source trees, which may not always be possible because
+they may share large portions of common code (which may further make
+concurrent development of the applications hard), or multiple Autoconf and
+Automake environments (multiple configure scripts) needs to be created
+in one source tree.  In this case the source tree usually gets very
+complicated and controlling what is compiled and what is included in
+distributions becomes harder, especially when different parts code is shared
+between applications and libraries.
+
+
+@node Integrating Autodist
+@chapter Integrating Autodist
+
+Integrating Autodist into existing software project can be a very simple
+task or a fairly complicated task.  It depends on the size and complexity
+of the software project.  Generally speaking, integrating Autodist into
+software project is fairly straightforward process:
+
+1. The distributions directory and 'default' distribution are created
+
+2. The 'configure.ad' is created
+
+3. If needed, 'Makefile.ad' file(s) are created
+
+After this the Autodist can already be used to prepare the source tree
+for configuration and compilation (@pxref{Preparing source tree, , , , }).
+Adding a new distribution would then allow the actual distribution
+packaging also.
+
+If the software project has had own ad-hoc distribution system already in
+place, it may take some work to move from that system into the Autodist.
+If there are multiple applications and distributions created from the
+source tree, the distributions and distribution defines for them need to
+be created.  While this may be unthankful job, it only needs to be done
+once.
+
+Integrating Autodist into a new software project is a very simple task as
+renaming 'configure.ac' and possibly 'Makefile.am' files are not required,
+as they may not exist yet.
+
+
+@menu
+* Creating distdir::            Creating distributions directory
+* autodist.conf::               Configuring Autodist
+* Creating new distribution::   Adding new distribution
+* Distribution file format::    Detailed document for distfile format
+* configure.ad files::          configure script for creating configure.ac
+* Makefile.ad files::           Makefile.ad for creating Makefile.am
+* Other .ad files::             Other files with .ad suffix
+* Distdefines::                 Using distdefs in files
+@end menu
+
+
+@node Creating distdir
+@section Creating distributions directory
+
+The distributions directory is 'distdir', which is expected to be
+located in the root of the source tree.  This directory will hold all
+the distribution files, and the Autodist configuration file 'autodist.conf' (@pxref{autodist.conf, , , , }).
+If this directory does not exist it can be created with the Autodist.
+
+@example
+  autodist -i
+@end example
+
+This will create the 'distdir' and copy the default 'autodist.conf'
+configuration file and the 'default' distribution into the directory.
+The 'default' distribution will be used by default by the Autodist
+unless other distribution is specified.
+
+After this the Autodist has effectively been integrated into the
+software project.  However, usually after this, one would create new
+distributions, the 'configure.ad' and possibly 'Makefile.ad' file(s).
+Without 'configure.ad' file a distribution package cannot be created.
+However, even without 'configure.ad' file the source tree can be
+prepared for configuration and compilation (@pxref{Preparing source tree, , , , }).
+
+@menu
+* autodist.conf::               Configuring Autodist
+@end menu
+
+
+@node autodist.conf
+@section Configuring Autodist
+
+After the Autodist has been integrated into the software by creating
+the 'distdir', the 'autodist.conf' configuration file was added to the
+'distdir' also.  Usually software projects will want to modify some of
+the 'autodist.conf' options, mainly specifying the distdef prefix.
+
+The 'autodist.conf' is a text file.  The following options are available
+in 'autodist.conf':
+
+
+@example
+DISTPREFIX=""
+@end example
+
+By default the distdef prefix is '_DIST_'.  To add own software package
+specific prefix the 'DISTPREFIX' can be defined.
+
+Example:
+@example
+DISTPREFIX="SILC"
+@end example
+
+Will set the distdef prefix as 'SILC_DIST_'.
+
+
+@example
+DISTDEFS="distdefs.h"
+@end example
+
+The 'DISTDEFS' option specifies the file name of the distdef header file
+which Autodist will create.  The software project should '#include' the
+header file in order for the preprocessor to respect the distdef
+conditionals (@pxref{Distdefines, , , , }).  By default the file name
+is 'distdefs.h' and is created at the root of source tree.  Other location
+may be specified if needed.
+
+Example:
+@example
+DISTDEFS="include/distdefs.h"
+@end example
+
+
+@example
+ACLOCAL="aclocal"
+@end example
+
+The 'ACLOCAL' specifies the location of the 'aclocal' tool.  If Autodist
+should not run 'aclocal' this option may be removed or set to empty value.
+User need to then run it manually.
+
+
+@example
+AUTOHEADER="autoheader"
+@end example
+
+The 'AUTOHEADER' specifies the location of the 'autoheader' tool.  If
+Autodist should not run 'autoheader' this option may be removed or set
+to empty value.  User need to then run it manually.
+
+@example
+AUTOCONF="autoconf"
+@end example
+
+The 'AUTOCONF' specifies the location of the 'autoconf' tool.  If
+Autodist should not run 'autoconf' this option may be removed or set
+to empty value.  User need to then run it manually.
+
+
+@example
+AUTOMAKE="automake -a -c"
+@end example
+
+The 'AUTOMAKE' specifies the location of the 'automake' tool.  If
+Autodist should not run 'automake' this option may be removed or set
+to empty value.  User need to then run it manually.  By default, the
+'-a'  and '-c' options are given to 'automake' to add any missing required 
+files.
+
+
+@example
+LIBTOOLIZE="libtoolize --automake -c"
+@end example
+
+The 'LIBTOOLIZE' specifies the location of the 'libtoolize' tool.
+This option should be removed or ste to empty value if 'libtool' is not
+used in the source tree.
+
+
+@example
+MAKE=make
+@end example
+
+The 'MAKE' specifies the location of the 'make' program.  This option must
+be set to valid value in order to create distributions.
+
+
+@menu
+* Creating new distribution::   Adding new distribution
+@end menu
+
+
+@node Creating new distribution
+@section Creating new distribution
+
+After the Autodist has been integrated into the software project by
+creating the 'distdir' and 'default' distribution, the source tree
+can be prepared for configuration and compilation (@pxref{Preparing source tree, , , , }).  However, the 'default' distribution should be used only as
+a development distribution.  Usually it is used to prepare the raw source
+tree (such as a tree just checkout
+from CVS) for configuration and compilation.  By default, the 'default'
+distribution cannot be packaged.  However, if the software project is
+small (one distribution), it may be convenient to edit the 'default'
+distribution to be as the distribution that is packaged from the source
+tree.  In software project where multiple distributions are created using
+the 'default' only as a development distribution is recommended.  The
+real distributions should be defined as separate distributions.
+
+Creating a new distribution is a simple process.  Each distribution
+is placed in the 'distdir' and the file name of the distribution file is
+used to reference to it.  By default, the distribution name is the
+file name of the distribution file.  The actual distribution file is
+a simple text file with various directives that define the distribution.
+
+If the 'default' distribution is used as a development distribution it
+might be desired to inherit some or all of the created distributions in
+it, so that development becomes possible with the 'default' distribution.
+Adding 'inherit' directive into the 'distdir/default' will inherit the
+specified distribution.
+
+
+@menu
+* Distribution file format::    Detailed document for distfile format
+@end menu
+
+
+@node Distribution file format
+@section Distribution file format in detail
+
+The distribution file, or distfile from now on, defines your distribution,
+distribution defines, options, included and excluded files and
+directories, license, and additional processing.  Each distribution is
+defined in a separate file and the distributions are referenced by
+their file name.
+
+The distfile is a text file that contains various directives that define
+the actual distribution.  Lines starting with '#' are considered comments
+and are ignored.
+
+
+@section Directive: name <name>
+
+The 'name' directive defines the name of the distribution.  It is optional
+directive, and if omitted the distribution name will be the name of the
+distfile.
+
+Example:
+@example
+name FOO Application
+@end example
+
+Will set your distribution name as 'Foo Application'.
+
+
+@section Directive: package <package>
+
+The 'package' directive defines the name of the distribution package.  It is
+optional directive, and if omitted the distribution package name will
+be the name of the distribution, if defined, or if omitted, then the name
+of the distfile.  If this directive is omitted then normal GNU convention
+is used to decide the package name, derived from the distribution name.
+
+Example:
+@example
+package foo-client
+@end example
+
+Will create distribution packages named, for example, as
+'foo-client-1.0.tar.gz'.
+
+
+@section Directive: bug-report <email address>
+
+The 'bug-report' directive can be used to define the email address where
+the bug-reports for the distribution should be sent.  The directive is
+optional.  The 'bug-report' email address will be set for the Autoconf
+which will deliver it via AC_INIT macro.
+
+
+@section Directive: license <filename>
+
+The 'license' directive can be used to define the license file for the
+distribution.  This directive is optional.  The license file will be
+copied into the distribution in the name 'COPYING'.  If the 'COPYING'
+file already exist it will be replaced.
+
+Example:
+@example
+license license/GPL
+@end example
+
+Will include the file 'license/GPL' into the distribution in the file
+name 'COPYING'.
+
+
+@section Directive: license-header <current-license> <new-license>
+
+The 'license-header' can be used to re-license your files into a new
+license.  This directive is optional.  There may be zero or more
+'license-header' directives in distribution.  The 'license-header'
+directive will compare the license header that usually appear at the
+start of a file to the <current-license>.  If it matches it will
+be replaced with the <new-license>.  The license header in the file
+will be replaced and the file will have effectively been re-licensed.
+
+Example:
+@example
+license-header license/BSD-header license/GPL-header
+@end example
+
+Will replace all appearances of the license header in 'license/BSD-header'
+file to the license header in 'license/GPL-header' in any file in the
+distribution.  Note that, the header change will be performed when
+the distribution is packaged (@pxref{Creating distribution, , , , }).
+
+With 'license-header' directive you may initially set your files in the
+source tree into what ever license you prefer.  However, if you need to
+re-license parts of the source tree in certain distributions the
+'license-header' will achieve this automatically.  For example, suppose
+one wants to create two different versions of a library distribution, with
+different feature sets, in two different licenses.
+
+There are several limitations in the current implementation of Autodist
+with the 'license-header' directive:
+
+First limitation is that the header files must have equal amount of lines.
+If the new header file has fewer lines that the current header file, all
+of the lines from the current header will not be replaced.  If the new header
+has fewer lines, empty lines must be added to it.  If the new header file
+has more lines than the current header file, the extra lines will not appear
+in the replaced header.  Basic rule is to always make sure the header file
+has equal amount of lines in them.
+
+Second limitation is in indentation of the header files.  It is suggested,
+though not mandatory, that the header files have the same indentation as
+is commonly used in the source tree; if the license header text in a file
+starts at the second character instead of at the start of the line, then
+the header file should start the license text at the second character also.
+If same indentation is not used the appearance of the replaced header
+may not be perfect.  While this is a cosmetic issue, one still to remember.
+
+Example current header:
+@example
+--- Start example
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+--- end example
+@end example
+
+Example new header:
+@example
+--- Start example
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the conditions listed in the
+  COPYING file are met.
+
+
+
+--- end example
+@end example
+
+In this example, if the text in the current header file is found in any
+file in the distribution it will be replaced with the new header file.
+Notice that, both header files has same amount of lines (8 lines).
+
+Note that, the current header must match exactly the header used in 
+files.  Otherwise the replacement will not be complete.
+
+
+@section Directive: inherit <distfile>
+
+The Autodist provides inheritance of distributions.  The 'inherit'
+directive is used to define the distribution which will be inherited
+into the distribution.  The <distfile> specifies the name of the
+inherited distribution.  If the distribution cannot be inherited Autodist
+will give an error.
+
+The 'inherit' will inherit the following information from the distribution:
+distdefs, undefines, includes, excludes and noprocess.  Other information
+will not be inherited.  If the inherited distribution inherits other
+distributions, they will also be inherited automatically.  User should be
+careful when inheriting distributions as it may be possible to create an
+infinite recursion.  The Autodist would allow for this and not detect this
+error.  Zero or more 'inherit' directives may be set for distribution.
+
+Example:
+@example
+inherit common
+inherit client
+inherit toolkit
+@end example
+
+Will inherit distributions 'common', 'client' and 'toolkit' into this
+distribution.  All distdefs, undefines, includes, excludes and noprocesses
+from these distributions are now also part this distribution.
+
+
+@section Directive: define <symbol>
+
+The 'define' directive is used to define the distdef symbols for the
+distribution.  This directive is optional, however, all distributions
+should define at least one distdef so that the distribution may be
+controlled with the distdef conditionals in files in the source tree (@pxref{Distdefines, , , , }).  By default, the distdef prefix is '_DIST_'.  Many
+software projects will want to set their own prefix for the distdefs
+for consistency.  The prefix may be defined in the 'autodist.conf' file
+(@pxref{autodist.conf, , , , }).
+
+Example:
+@example
+define _DIST_FOO
+define _DIST_FEATURE_X
+define _DIST_LIBRARY_Y
+@end example
+
+Will define the following distdefs for the distribution: '_DIST_FOO',
+'_DIST_FEATURE_X' and '_DIST_LIBRARY_Y'.  These distdefs may then be
+used in the source tree and source code to control what is included in
+or excluded from this distribution.
+
+
+@section Directive: undef <symbol>
+
+The 'undef' directive may be used to explicitly undefine a distdef.
+When inheriting distributions it may be desired to be able undefine
+certain distdefs.  This directive is optional.
+
+Example:
+@example
+undef _DIST_FEATURE_Y
+@end example
+
+Will undefine '_DIST_FEATURE_Y' distdef.  This distdef will not be part
+of this distribution anymore, even if it is defined in some inherited
+distribution.
+
+
+@section Directive: option <option> [...]
+
+The 'option' directive is used to define various options for the
+distribution.  The options can change the behavior of the distribution.
+This directive is optional.  One or more options may be defined in one
+'option' directive.  Zero or more 'option' directives may be set for
+distribution.  The following options are available.
+
+@example
+template
+@end example
+
+When set, the distribution is a template distribution.  Templates are
+special distributions which cannot be prepared or packaged with Autodist.
+Templates can only be inherited.  Usually, templates are used to define a
+common template distribution for other distributions.  Templates may set
+distdefs, undefines, includes and excludes.  A large software project
+could have several distributions that share a common base.  In this case
+defining the common base as a template distribution and then inheriting
+that distribution makes it easier to manage the distfiles.
+
+@example
+no-dist
+@end example
+
+Distributions with the 'no-dist' option are similar to templates, except
+that they can be prepared with Autodist, but they cannot be packaged.
+These are usually used as a common development distribution, such as the
+'default' distribution created with 'autodist -i'.
+
+@example
+no-inherit
+@end example
+
+If this option is set to normal distributions or distributions with
+'no-dist' option, the distribution cannot be inherited.  For template
+this option has no effect.  If distribution with this option is inherited
+the Autodist will give an error.
+
+
+@section Directive: include <source> [<destination>]
+
+The 'include' directive can be used to include files or directories into
+the distribution.  Sometimes it may be desired to specify included
+files and directories in distribution instead of Makefile.am and
+EXTRA_DIST, especially if there are many distributions that need to
+include specific files and directories.  While it would be possible
+to define them in Makefile.ad and use distdef conditionals to define
+which will be included in which distribution, if there are many different
+distributions it may pollute the Makefile.ad unnecessarily.
+
+This directive is optional.  The <source> may be a single file, a  single
+directory or a regular expression which will match several files and/or
+directories.  The <destination> is optional.  If it is omitted then
+the <source> will be copied into the same location in the distribution.
+If the <destination> is provided the <source> will be copied into the
+specified location.
+
+Example:
+@example
+include apps/foobar/README README
+include lib/libfoo
+include lib/libfoobar lib/foobarlib
+include doc/foo*
+include scripts/foobar.sh foo.sh
+@end example
+
+Will include the file 'apps/foobar/README' into the top distribution
+directory in the name 'README', the directory 'lib/libfoo' into same
+location in distribution, the directory 'lib/libfoobar' into
+'lib/foobarlib' changing the name of the directory into 'foobarlib',
+the files and directories that match 'doc/foo*' into the same locations
+in distribution, and finally the 'scripts/foobar.sh' into the top
+distribution directory changing the name of the file into 'foo.sh'.
+
+Note that, the 'include' directives will be processed by the Autodist
+only when the distribution is packaged (@pxref{Creating distribution, , , , }).  When preparing the source
+tree for configuration and compilation (@pxref{Preparing source tree, , , , })
+the 'include' directives are ignored.  This is same behavior as with
+Makefile.am's EXTRA_DIST.
+
+If the included file or directory does not exist the Autodist will
+give an error and stop the distribution creation.  If the destination
+file exist, it will be replaced with the included file.  If the
+destination directory already exists, the contents of the source
+directory will be copied into the directory.  Note that, the directory
+will not be copied into the directory; if the <destination> is specified,
+also the name of the <source> file or directory must be specified,
+otherwise the 'include' will change the name into the one specified.
+
+Example:
+@example
+include lib/libfoo lib
+@end example
+
+In this example the 'lib/libfoo' will be included as 'lib'.  If the 'lib'
+already exists, this effectively copies the contents of the 'lib/libfoo'
+into 'lib'.  In order to include the directory with same name, the
+name must be specified.
+
+Example:
+@example
+include lib/libfoo lib/libfoo
+include lib/foobar new_lib/foobar
+@end example
+
+This will include the 'lib/libfoo' into 'lib/libfoo' in distribution,
+and 'lib/foobar' into 'new_lib/foobar' in distribution.
+
+
+@section Directive: exclude <filename> [...]
+
+The 'exclude' directive can be used to exclude files and directories from
+the distribution.  This directive is optional.  This directive is
+processed before processing the 'include' directive.  The <filename>
+can be a single file, a single directory or a regular expression that
+will match several files and/or directories.
+
+Example:
+@example
+exclude README
+exclude doc/client*
+@end example
+
+This will exclude the file 'README' and anything that match 'doc/client*'.
+
+
+@section Directive: noprocess <filename> [...]
+
+The 'noprocess' directive can be used to tell Autodist specificly not to
+process a file.  The Autodist will not process the file during
+preparation or during distribution packaging.  This directive is optional.
+One or more file can be specified in the 'noprocess' directive.  Zero or
+more 'noprocess' directives can be used in distribution.  The <filename>
+can be a single file, a single directory or a regular expression that
+will match several files and/or directories.  If directory is specified
+then all files inside the directory will not be processed.
+
+Example:
+@example
+noprocess autodist.texi
+@end example
+
+Autodist will not process 'autodist.texi' file.
+
+Note that, 'noprocess' directive cannot be used to disallow processing
+of any file with '.ad' suffix.
+
+
+@section Directive: pre-hook <filename> [...]
+
+The 'pre-hook' directive can be used define additional scripts that
+will be run before the source tree is prepared.  This directive is
+optional.  One or more scripts may be defined in one 'pre-hook' directive.
+Zero or more 'pre-hook' directives may be set for distribution.  The
+'pre-hook' hook will be run immediately after invoking Autodist to start
+preparing the source tree for configuration and compilation (@pxref{Preparing source tree, , , , }).
+
+The scripts will get three (3) command line arguments when Autodist
+executes the script: distribution name, distribution version and package
+name of distribution.  The script may use these arguments if it needs them.
+
+
+@section Directive: post-hook <filename> [...]
+
+The 'post-hook' directive can be used define additional scripts that
+will be run after the source tree is prepared.  This directive is
+optional.  One or more scripts may be defined in one 'post-hook' directive.
+Zero or more 'post-hook' directives may be set for distribution.  The
+'post-hook' hook will be run immediately after the Autodist has finished
+preparing the source three for configuration and compilation (@pxref{Preparing source tree, , , , }).  The Autodist will exit after it has run the
+'post-hook' scripts.
+
+The scripts will get three (3) command line arguments when Autodist
+executes the script: distribution name, distribution version and package
+name of distribution.  The script may use these arguments if it needs them.
+
+
+@section Directive: pre-dist-hook <filename> [...]
+
+The 'pre-dist-hook' directive can be used define additional scripts that
+will be run when Autodist has started distribution creation.  This directive
+is optional.  One or more scripts may be defined in one 'pre-dist-hook'
+directive.  Zero or more 'pre-dist-hook' directives may be set for
+distribution.  The 'pre-dist-hook' hook will be run immediately after
+the Autodist has created the distribution directory but has not yet
+started any distribution processing.
+
+The scripts will get four (4) command line arguments when Autodist
+executes the script: distribution name, distribution version, package
+name of distribution and destination distribution directory name.  The
+script may use these arguments if it needs them.
+
+
+@section Directive: post-dist-hook <filename> [...]
+
+The 'post-dist-hook' directive can be used define additional scripts that
+will be run when Autodist has finished distribution processing.  This
+directive is optional.  One or more scripts may be defined in one
+'post-dist-hook' directive.  Zero or more 'post-dist-hook' directives may
+be set for distribution.  The 'post-dist-hook' hook will be run immediately
+after the Autodist has finished processing the destination distribution
+directory but has not yet created the distribution package.
+
+The scripts will get four (4) command line arguments when Autodist
+executes the script: distribution name, distribution version, package
+name of distribution and destination distribution directory name.  The
+script may use these arguments if it needs them.
+
+
+@section Example distfile
+
+The following is a simple distfile example.  The example assumes that the
+distdefs prefix is 'SILC'.
+
+@example
+# SILC Client distribution
+name SILC Client
+package silc-client
+bug-report silc-client-bugs@@silcnet.org
+inherit common
+inherit platform-unix
+inherit platform-win32
+define SILC_DIST_CLIENT
+define SILC_DIST_CLIENTLIB
+define SILC_DIST_IRSSI
+undef SILC_DIST_MPI
+exclude doc/draft*
+pre-hook scripts/client-pre-run
+post-dist-hook scripts/client-post-dist-run
+post-dist-hook scripts/client-post-dist-kludge
+@end example
+
+@menu
+* configure.ad files::          configure script for creating configure.ac
+@end menu
+
+
+@node configure.ad files
+@section configure.ad files
+
+Autodist creates 'configure.ac' file from the 'configure.ad' file.  The
+'configure.ad' file is a rather normal 'configure.ac' except that it accepts
+also Autodist macros.  Autodist also supports configure script fragments,
+also named as 'configure.ad'.  Any 'configure.ad' file in the source tree
+can be incorporated into the the top 'configure.ad' file.  Sometimes it may
+be useful to split a large configure script into smaller fragments.
+Especially in multi distribution system where certain libraries or features
+can be excluded from certain distributions it may be useful to handle
+their configuration from a configure fragment.  If the library is
+excluded then also its configuration can be excluded.
+
+If the software project already has a 'configure.ac' or 'configure.in'
+file, the 'configure.ad' can be created by simply renaming the current
+file to 'configure.ad'.  In this case the current configure script
+must be edited to support Autodist.  This is done by replacing the
+'AC_INIT' to 'AD_INIT'.  After specifying the 'AD_INIT' as the first
+macro in the 'configure.ad', the Autodist support has been fully
+integrated into the software project.
+
+If your software project is going to use configure fragments, then
+also Autodist macro 'AD_INCLUDE_CONFIGURE' must be used.  Autodist will
+automatically combine the fragments with the top 'configure.ac' script.
+To exclude a 'configure.ad' fragment from a distribution use the distdef
+conditionals inside the 'configure.ad' fragment file.  If the distdef is
+not defined the fragment will be excluded automatically.
+
+The following macros are available in current Autodist version.
+
+@defmac AD_INIT
+
+The 'AD_INIT' macro is used in place of Autoconf macro 'AC_INIT'.  The
+'AD_INIT' must be the first macro in the 'configure.ad', just like the
+'AC_INIT' macro in 'configure.ac'.  The AD_INIT macro is used to deliver
+the distribution names, distribution version, package name and bug-report
+email address to the 'configure.ac' file that Autodist will create.
+The 'AC_INIT' macro must not be used in 'configure.ad' file.
+
+This macro is mandatory and Autodist will exit with error if it is not
+specified in 'configure.ad'.  This macro has no arguments.
+@end defmac
+
+
+@defmac AD_INCLUDE_CONFIGURE
+
+This macro is used to tell Autodist that it should include any other
+'configure.ad' fragment that is found from the source tree into the
+top 'configure.ad' file.  Note that, the 'configure.ad' fragments will
+be incorporated at the location where this macro is used in the
+'configure.ad'.  Usually this macro is placed just before the Autoconf
+macro 'AC_OUTPUT'.  This macro has no arguments.
+
+Note that, the 'configure.ad' fragments are not real full featured
+configure scripts.  They must not use 'AD_INIT', 'AD_INCLUDE_CONFIGURE',
+'AC_INIT' or any other initialization macros.
+
+@end defmac
+
+@menu
+* Makefile.ad files::           Makefile.ad for creating Makefile.am
+@end menu
+
+
+@node Makefile.ad files
+@section Makefile.ad files
+
+Autodist creates 'Makefile.am' files from 'Makefile.ad' files.  A software
+project do not need to use 'Makefile.ad' files if there is no need to
+use distdef conditionals inside makefiles.  Usually a multi distribution
+software project, however will need to define certain things to different
+distributions.  In these cases 'Makefile.ad' file needs to be created.
+
+Even though it would be possible to use distdef conditionals also inside
+'Makefile.am' files, Autodist does not process 'Makefile.am' files when
+preparing the source tree for configuration and compilation (@pxref{Preparing source tree, , , , }).  Thus, the prepared environment would not be
+identical to the created distribution package (when the 'Makefile.am'
+will be processed), and configuration and compilation would be inconsistent.
+Basic rule is, if you need distdefs (@pxref{Distdefines, , , , }) inside
+makefiles, put them inside 'Makefile.ad' file.
+
+
+@menu
+* Other .ad files::             Other files with .ad suffix
+@end menu
+
+
+@node Other .ad files
+@section Other .ad files
+
+Any file in the source tree can have the '.ad' suffix appended.  Autodist
+will process any file that has the suffix when the source tree is
+prepared for configuration and compilation (@pxref{Preparing source tree, , , , }).  If the files have distdef conditionals the Autodist will process them.
+The files will have the '.ad' suffix removed.
+
+Basic rule is, if you need to process some file when preparing the
+source tree for configuration and compilation, add '.ad' suffix to it.
+Distdefs (@pxref{Distdefines, , , , }) can be used in any file in source
+tree but without '.ad' suffix Autodist will not process those files during
+preparation.  They will be processed when creating the distribution package.
+If you need processed files during configuration or compilation then they
+need to have '.ad' suffix.
+
+@menu
+* Distdefines::                 Using distdefs in files
+@end menu
+
+
+@node Distdefines
+@section Using distribution defines (distdefs)
+
+Distribution defines, or distdefs from now on, are used to define inside
+a file what will be included in the distribution.  Distribution may define
+many different distdefs, for example, based on feature sets, platforms, or
+for other similar reasons.  If distdef is not defined for the distribution
+but is used in a file, anything inside the distdef in that file will be
+removed when the distribution is packaged (@pxref{Creating distribution, , , , }).  This guarantees that only the files, directories and file content
+(such as source code) that is supposed to be delivered with the distribution
+are delivered.  Delivering files or code accidentally in the distribution
+cannot happen.
+
+All other files, except files ending with '.ad' suffix are processed for
+distdefs only when the distribution is packaged.  Files ending with '.ad'
+suffix are processed for distdefs when preparing the source tree for
+configuration and compilation (@pxref{Preparing source tree, , , , }).
+
+By default the distdefs are named '_DIST_XXX', where 'XXX' is the name of
+distdef.  However, many projects will want to define their own prefix
+for distdefs in the 'autodist.conf' configuration file (@pxref{autodist.conf, , , , }).
+In the following examples a prefix 'SILC' is used, hence the prefix for 
+the distdefs are 'SILC_DIST_'.
+
+The basic format for the distdefs are as follows:
+
+@example
+#ifdef SILC_DIST_DEFINE
+#endif SILC_DIST_DEFINE
+
+#ifndef SILC_DIST_DEFINE
+#endif SILC_DIST_DEFINE
+
+#ifdef SILC_DIST_DEFINE
+#else !SILC_DIST_DEFINE
+#endif SILC_DIST_DEFINE
+
+#ifndef SILC_DIST_DEFINE
+#else SILC_DIST_DEFINE
+#endif SILC_DIST_DEFINE
+@end example
+
+This format should be used only in non-source files, as for example C and
+C++ compilers will not like this format inside a file.  In source files
+a compiler friendly format, defined below, should be used.
+
+@example
+#ifdef SILC_DIST_DEFINE
+#endif /* SILC_DIST_DEFINE */
+
+#ifndef SILC_DIST_DEFINE
+#endif /* SILC_DIST_DEFINE */
+
+#ifdef SILC_DIST_DEFINE
+#else /* !SILC_DIST_DEFINE */
+#endif /* SILC_DIST_DEFINE */
+
+#ifndef SILC_DIST_DEFINE
+#else /* SILC_DIST_DEFINE */
+#endif /* SILC_DIST_DEFINE */
+@end example
+
+Note that, only the format defined above is supported.  Other more complex
+use of the preprocessor directives such as using '&&' and '||' in the '#ifdef'
+or '#ifndef' are not supported, and neither is '#elif'.  Also note, that in
+the compiler friendly format the name of the distdef in comments and the
+use of '!' character in the '#else' branch of '#ifdef' are mandatory.  Also
+note, that the distdef conditionals must be placed at the start of the line,
+they must not be indented.
+
+The following example shows the use of non-source format:
+
+@example
+SUBDIRS =                        \
+#ifdef SILC_DIST_SERVER
+       server                    \
+       server-foobar             \
+#endif SILC_DIST_SERVER
+#ifndef SILC_DIST_CLIENT
+       tests                     \
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_TOOLKIT
+       toolkit                   \
+       toolkit-docs              \
+#else !SILC_DIST_TOOLKIT
+       doc                       \
+       lib                       \
+#ifdef SILC_DIST_CLIENT
+       client                    \
+#endif SILC_DIST_CLIENT
+#endif SILC_DIST_TOOLKIT
+@end example
+
+Say, in this example, your distribution has the SILC_DIST_CLIENT and
+SILC_DIST_SERVER defined, but not the SILC_DIST_TOOLKIT, the end result
+would be:
+
+@example
+SUBDIRS =                        \
+       server                    \
+       server-foobar             \
+       doc                       \
+       lib                       \
+       client                    \
+@end example
+
+The lines defined specificly for the SILC_DIST_TOOLKIT, which in our
+example was not defined, were removed.  Also lines that specificly
+expected certain distdefs not to be defined ('#ifndef') were removed.
+(Note the last remaining '\' in example above would be removed by the
+Autodist automatically to avoid errors with Automake.)
+
+The following example shows the use of source code format:
+
+@example
+  initialize_lib();
+#ifdef SILC_DIST_MPI
+  init_mpi();
+  mpi = mpi_alloc();
+#else /* !SILC_DIST_MPI */
+  init_gmp();
+#endif /* SILC_DIST_MPI */
+
+#ifndef SILC_DIST_FOOBAR
+  foobar_replacement();
+#else /* SILC_DIST_FOOBAR */
+  real_foobar();
+#endif /* SILC_DIST_FOOBAR */
+@end example
+
+Say, you have both SILC_DIST_MPI and SILC_DIST_FOOBAR defined, the end result
+would be:
+
+@example
+  initialize_lib();
+  init_mpi();
+  mpi = mpi_alloc();
+
+  real_foobar();
+@end example
+
+Even before processing the source files with Autodist, the preprocessor 
+will respect the preprocessor directives if the code use '#include' to 
+include the distdef header file created by the Autodist (see 
+'autodist.conf' (@pxref{autodist.conf, , , , })).  When the distribution 
+is packaged (@pxref{Creating distribution, , , , }) the Autodist will 
+process the files, and will remove any line not defined to be included.  
+The preprocessor directives will also be removed.
+
+Because the software project includes the header file with '#include' the 
+distdef header file needs to be present in the distribution, unless it is 
+placed inside some other '#ifdef' conditional.  If the distribution is
+prepared but not compiled (it is packaged after preparation without
+compilation) then including the distdef header in the source is not 
+necessary.  Including it then in the distribution is not necessary either.
+The software project should not use the same name space that distdef
+conditionals use for other than distribution usage.  The Autodist will
+process any line that uses the formats above and has the specified prefix
+(eg. 'SILC_DIST_') in those lines.  Using same prefix for other purposes
+will produce unexpected results and invalid distributions.
+
+The following suffixes will be considered as source files by the Autodist:
+
+@example
+    .c
+    .C
+    .cc
+    .cp
+    .cpp
+    .CPP
+    .cxx
+    .CXX
+    .c++
+    .m
+    .h
+    .H
+    .hh
+@end example
+
+Using distdefs in any other file must follow the non-source format.
+
+
+@node Invoking Autodist
+@chapter Invoking Autodist
+
+The Autodist has two basic functions:
+
+    1. Preparing source tree for configuration and compilation (@pxref{Preparing source tree, , , , })
+
+    2. Creating distribution packages (@pxref{Creating distribution, , , , })
+
+The 'autodist' accepts the following options:
+
+@table @samp
+
+@item -h
+@itemx --help
+Prints the help for the Autodist and exits.
+
+@item -V
+@itemx --version
+Prints version number and exits.
+
+@item -v
+@itemx --verbose
+Verbosely report processing.
+
+@item -d
+@itemx --distdir <dir>
+Search distributions from <dir> instead of default 'distdir'.
+
+@item -s
+@itemx --distdefs [<dist>]
+Prints distribution defines of <dist> and exits.
+
+@item -i
+@itemx --init
+Initializes Autodist environment.  Creates the default distribution
+directory 'distdir', 'autodist.conf' configuration file and the
+default distribution 'default', then exits.
+
+@item -m
+@itemx --makedist
+Creates and packages distribution
+
+@itemx --gzip
+Create package compressed with gzip (default)
+
+@itemx --bzip2
+Create also package compressed with bzip2
+
+@itemx --compress
+Create also package compressed with compress
+
+@itemx --zip
+Create also package compressed with zip
+
+
+@end table
+
+@menu
+* Preparing source tree::       Preparing source tree with Autodist
+* Creating distribution::       Creating distribution with Autodist
+@end menu
+
+
+@node Preparing source tree
+@section Preparing source tree for configuration and compilation
+
+Before distribution can be created from the source tree, the source tree
+must be prepared for configuration and compilation.  If your project is
+not using Autodist, then you would do this by running perhaps 'aclocal',
+'autoconf', 'autoheader' and 'automake' tools manually, or you would run an
+'autogen.sh' script that prepares your raw source tree.  With Autodist
+this process is performed by Autodist, and running these tools manually
+or using 'autogen.sh' script is not necessary.
+
+By default the 'autodist.conf' (@pxref{autodist.conf, , , , }) has defined 
+the tools that will be run by the Autodist when preparing the source tree.  
+These are 'aclocal', 'autoheader', 'autoconf', 'automake' and 
+'libtoolize'.  If you do not whish that Autodist runs some or any of these 
+tools automatically, do not set them in the 'autodist.conf'.  You would 
+then need to run them manually. However, this is not recommended.  If you 
+need to run additional preparation scripts you may set your scripts either 
+in the 'pre-hook' and/or 'post-hook' where you can run what ever 
+additional processing you may need to prepare your source tree.
+
+By default the Autodist creates a 'default' distribution when you
+initialize your project by running 'autodist -i'.  The 'default'
+distribution should be used when you are developing in your source
+tree.  By default, the 'default' distribution cannot be packaged,
+however, if your project creates only one distribution you may find
+it more convenient to define your distribution inside the 'default'
+distribution and allow it to be packaged also.  If your source tree
+will create multiple distributions, the 'default' should be used only
+as development distribution.  You would use it when you, for example,
+checkout your source tree from CVS and prepare it for configuration
+and compilation.  To prepare your source tree with the 'default'
+distribution run Autodist without any arguments.
+
+@example
+  autodist
+@end example
+
+The Autodist will prepare your source tree.  After that you may run
+'./configure' and continue to compile with 'make'.
+
+If you do not whish to use the 'default' distribution, or you whish
+to do the development in a tree specificly prepared for some specific
+distribution, or you are preparing to create a new distribution package,
+you will need to run the Autodist with the distribution you whish to
+prepare.
+
+@example
+  autodist example-distribution 1.0.3
+@end example
+
+This prepares your source tree for 'example-distribution' of version
+'1.0.3'.  After that you may run './configure' and continue to compile
+with 'make'.  If the version is omitted the version will be '0.0'.
+
+Note that, running Autodist for preparation merely prepares your source
+tree for the distribution, it does not create an actual distribution
+package.  When preparing source tree for configuration and compilation
+the Autodist will process any file that ends with '.ad' suffix.  It will
+process all 'configure.ad' and 'Makefile.ad' files for that distribution.
+When you run './configure' your tree will be configured for that
+distribution, and when you compile with 'make' it will compile for that
+distribution.
+
+However, the source files, or any other file (except files ending with
+'.ad' suffix) are not processed by the Autodist.  When compiling
+your sources the preprocessor, however, will respect your distdef
+conditionals inside your source files if you include the distdef header
+file.  This way, even the compiled binaries will be compiled for that
+distribution, even though the source files has not yet been processed
+by the Autodist.  Rest of the files in the distribution will be processed
+when you create the actual distribution package.  It is guaranteed that
+the distribution you have prepared will behave in your source tree exactly
+the same way as if it was already packaged with Autodist (providing that
+you remember to include the distdef header file in your code).
+
+@menu
+* Creating distribution::       Creating distribution with Autodist
+@end menu
+
+
+@node Creating distribution
+@section Creating distribution package(s)
+
+Before creating a new distribution package, you will need to prepare
+the source tree for the distribution you want to create.  After preparing
+your source tree you will be ready to create a new distribution.  The
+Autodist package provides a simple helper script 'makedist' that may
+be used to create the distribution.  However, if you whish, you may
+run the Autodist yourself, as the 'makedist' will call Autodist anyway.
+
+To create a new distribution for the distribution you have prepared for
+run makedist.
+
+@example
+  makedist
+@end example
+
+This will run the Autodist and create a new distribution package that
+is archived with 'tar' and compressed with 'gzip'.  If you whish to
+create packages also compressed with 'bzip2', 'compress' and/or 'zip'
+you may give one or all of the following options:
+
+@example
+  makedist --bzip2 --compress --zip
+@end example
+
+This example would create, in addition of 'tar.gz' package, also a
+'tar.bz2', 'tar.Z' and '.zip' packages.  Current version of Autodist does
+not support archiving with 'shar'.
+
+If you whish to run additional processing for your distributions when
+they are being packaged you may set 'pre-dist-hook' and/or 'post-dist-hook'
+in your distribution file.  Also note that any hooks provided by Automake
+in Makefiles will be run in normal manner.
+
+For additional help, you may give:
+
+@example
+  makedist --help
+@end example
+
+
+@node Examples
+@chapter Examples
+
+@menu
+* Single distribution tree::    Single distribution example
+* Multiple distribution tree::  Multiple distributions example
+@end menu
+
+@node Single distribution tree
+@section Single distribution tree example, start to finish
+
+Lets suppose you have a simple source tree with one application,
+called 'foozbar' you whish to release.  While you would probably suffice
+using Autoconf and Automake features you may still use Autodist.
+
+First, you create the default 'distdir' into your software package:
+
+@example
+  autodist -i
+@end example
+
+Then, you create the 'configure.ad' file from your existing 'configure.ac'
+or 'configure.in' file.  If you don't have configure script written yet,
+please refer to the Autoconf manual.  In the 'autodist.ad' you add as
+first macro in the file:
+
+@example
+  AD_INIT
+@end example
+
+Then, you create distribution file for your application:
+
+@example
+# Foozbar distribution
+name Foozbar
+package foozbar
+bug-report foozbar-bugs@@foo.z.bar
+define _DIST_FOOZBAR
+@end example
+
+This distribution file go into 'distdir/foozbar'.
+
+And there you go.  You have succesfully integrated Autodist into your
+source tree.  If you need to do development and you whish to use the
+'default' distribution for that, you should inherit the new 'foozbar'
+distribution in it.  Add the following line in 'distdir/default':
+
+@example
+  inherit foozbar
+@end example
+
+After that, you can prepare the source tree for configuration and
+compilation by giving:
+
+@example
+  autodist
+@end example
+
+After this command you can give './configure' and 'make'.
+
+If you want to do development directly in a tree prepared for the
+'foozbar' distribution, or you are ready to start creating a new
+distribution package, you give:
+
+@example
+  autodist foozbar 1.0
+@end example
+
+After this command you can give './configure' and 'make'.
+
+To create the distribution package, you will give:
+
+@example
+  makedist
+@end example
+
+The end result will be a 'foozbar-1.0.tar.gz' package.
+
+
+@node Multiple distribution tree
+@section Multiple distribution tree example, start to finish
+
+Lets suppose you have a source tree from which you create multiple
+distributions, say three.  If you really have a such source tree you
+must have by now noticed the difficulty of maintaining such a source tree
+and problems with controlling the distributions.  Maybe you have sufficed
+with Autoconf and Automake, or perhaps you have created your own scripts
+that carry out the kludges.  No more, for Autodist is here.
+
+First, you integrate Autodist into your tree by creating the distributions
+directory 'distdir':
+
+@example
+  autodist -i
+@end example
+
+Then, you create the 'configure.ad' file from your existing 'configure.ac'
+or 'configure.in' file.  If you don't have configure script written yet,
+please refer to the Autoconf manual.  In the 'autodist.ad' you add as
+first macro in the file:
+
+@example
+  AD_INIT
+@end example
+
+You then continue with creating the distribution files for your three
+distributions.  Let's name them 'foozbar', 'libfoozbar' and 'nomad'.
+We will also create a common template that all distributions inherit.
+
+@example
+# Foozbar distribution
+name Foozbar
+package foozbar
+bug-report foozbar-bugs@@foo.z.bar
+inherit common
+define _DIST_FOOZBAR
+@end example
+
+@example
+# libfoozbar distribution
+name libfoozbar
+bug-report libfoozbar-bugs@@foo.z.bar
+inherit common
+define _DIST_LIBFOOZBAR
+@end example
+
+@example
+# Nomad distribution
+name Nomad
+package nomad-the-server
+bug-report nomad-bugs@@foo.z.bar
+inherit common
+include doc/nomad
+define _DIST_NOMAD
+define _DIST_NOMAD_LIB
+undef _DIST_CRYPTO
+@end example
+
+@example
+# Common template
+define _DIST_DOC
+define _DIST_LIB
+define _DIST_MATH
+define _DIST_CRYPTO
+define _DIST_UNIX
+define _DIST_MACOSX
+define _DIST_WIN32
+@end example
+
+You put the distribution files in the 'distdir' directory.  In addition
+you will be doing development in the source tree using the 'default'
+distribution, you will add the new distributions to the 'distdir/default':
+
+@example
+inherit foozbar
+inherit libfoozbar
+inherit nomad
+@end example
+
+To prepare the source tree for configuration and compilation you would
+simply give:
+
+@example
+autodist
+@end example
+
+This will prepare your source tree for configuration and compilation.  Since
+the 'default' distribution inherits all distributions your development
+source tree will have all of them included.  If you do not want to do this
+then don't inherit them in the 'default', but run the autodist specificly
+for the distributions, for example:
+
+@example
+autodist foozbar
+@end example
+
+Since all the distributions inherit the 'common' distribution they get
+all the distdefs that the 'common' defines.  In this example various distdefs
+has been defined.  You would use them in your code and in your makefiles
+to control various things.  For example, let's say the 'common' distdefs
+control what directories distributions have.  An example 'Makefile.ad'
+file:
+
+@example
+SUBDIRS =                       \
+#ifdef _DIST_LIB
+       lib                      \
+#endif _DIST_LIB
+#ifdef _DIST_DOC
+       doc                      \
+#endif _DIST_DOC
+@end example
+
+Perhaps the 'Makefile.ad' in 'lib' subdirectory could define something
+like this:
+
+@example
+SUBDIRS =                       \
+        util                    \
+#ifdef _DIST_MATH
+        mathlib                 \
+#endif _DIST_MATH
+#ifdef _DIST_CRYPTO
+        cryptolib               \
+#endif _DIST_CRYPTO
+#ifdef _DIST_NOMAD_LIB
+        nomadlib                \
+#endif _DIST_NOMAD_LIB
+#ifdef _DIST_LIBFOOZBAR
+        foozbarlib               \
+#endif _DIST_LIBFOOZBAR
+@end example
+
+Since the 'nomad' distribution undefined the '_DIST_CRYPTO' distdef it
+would not have the 'cryptolib' in its distribution.  Clearly Nomad
+don't need it.  In addition of using the distdefs just in the makefiles
+you may want to use them in the source code as well:
+
+@example
+     ...some code...
+
+#ifdef _DIST_MATH
+  /* Initialize math library */
+  math_init();
+#endif /* _DIST_MATH */
+
+     ...some code...
+@end example
+
+After an intensive development period you're ready to create new releases.
+Let's say you're going to release all distributions:
+
+First you release Foozbar 0.5.1:
+
+@example
+autodist foozbar 0.5.1
+makedist --bzip2
+@end example
+
+The end result is two files: 'foozbar-0.5.1.tar.gz' and
+'foozbar-0.5.1.tar.bz2'.
+
+Then you continue with libfoozbar and Nomad:
+
+@example
+autodist libfoozbar 1.0.5
+makedist
+
+autodist nomad 2.0
+makedist
+@end example
+
+The end results are: 'libfoozbar-1.0.5.tar.gz' and 'nomad-2.0.tar.gz'.
+
+@page
+@contents
+@bye
diff --git a/apps/autodist/doc/fdl.texi b/apps/autodist/doc/fdl.texi
new file mode 100644 (file)
index 0000000..5385f32
--- /dev/null
@@ -0,0 +1,452 @@
+
+@node GNU Free Documentation License
+@appendixsec GNU Free Documentation License
+
+@cindex FDL, GNU Free Documentation License
+@center Version 1.2, November 2002
+
+@display
+Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA  02111-1307, USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+@end display
+
+@enumerate 0
+@item
+PREAMBLE
+
+The purpose of this License is to make a manual, textbook, or other
+functional and useful document @dfn{free} in the sense of freedom: to
+assure everyone the effective freedom to copy and redistribute it,
+with or without modifying it, either commercially or noncommercially.
+Secondarily, this License preserves for the author and publisher a way
+to get credit for their work, while not being considered responsible
+for modifications made by others.
+
+This License is a kind of ``copyleft'', which means that derivative
+works of the document must themselves be free in the same sense.  It
+complements the GNU General Public License, which is a copyleft
+license designed for free software.
+
+We have designed this License in order to use it for manuals for free
+software, because free software needs free documentation: a free
+program should come with manuals providing the same freedoms that the
+software does.  But this License is not limited to software manuals;
+it can be used for any textual work, regardless of subject matter or
+whether it is published as a printed book.  We recommend this License
+principally for works whose purpose is instruction or reference.
+
+@item
+APPLICABILITY AND DEFINITIONS
+
+This License applies to any manual or other work, in any medium, that
+contains a notice placed by the copyright holder saying it can be
+distributed under the terms of this License.  Such a notice grants a
+world-wide, royalty-free license, unlimited in duration, to use that
+work under the conditions stated herein.  The ``Document'', below,
+refers to any such manual or work.  Any member of the public is a
+licensee, and is addressed as ``you''.  You accept the license if you
+copy, modify or distribute the work in a way requiring permission
+under copyright law.
+
+A ``Modified Version'' of the Document means any work containing the
+Document or a portion of it, either copied verbatim, or with
+modifications and/or translated into another language.
+
+A ``Secondary Section'' is a named appendix or a front-matter section
+of the Document that deals exclusively with the relationship of the
+publishers or authors of the Document to the Document's overall
+subject (or to related matters) and contains nothing that could fall
+directly within that overall subject.  (Thus, if the Document is in
+part a textbook of mathematics, a Secondary Section may not explain
+any mathematics.)  The relationship could be a matter of historical
+connection with the subject or with related matters, or of legal,
+commercial, philosophical, ethical or political position regarding
+them.
+
+The ``Invariant Sections'' are certain Secondary Sections whose titles
+are designated, as being those of Invariant Sections, in the notice
+that says that the Document is released under this License.  If a
+section does not fit the above definition of Secondary then it is not
+allowed to be designated as Invariant.  The Document may contain zero
+Invariant Sections.  If the Document does not identify any Invariant
+Sections then there are none.
+
+The ``Cover Texts'' are certain short passages of text that are listed,
+as Front-Cover Texts or Back-Cover Texts, in the notice that says that
+the Document is released under this License.  A Front-Cover Text may
+be at most 5 words, and a Back-Cover Text may be at most 25 words.
+
+A ``Transparent'' copy of the Document means a machine-readable copy,
+represented in a format whose specification is available to the
+general public, that is suitable for revising the document
+straightforwardly with generic text editors or (for images composed of
+pixels) generic paint programs or (for drawings) some widely available
+drawing editor, and that is suitable for input to text formatters or
+for automatic translation to a variety of formats suitable for input
+to text formatters.  A copy made in an otherwise Transparent file
+format whose markup, or absence of markup, has been arranged to thwart
+or discourage subsequent modification by readers is not Transparent.
+An image format is not Transparent if used for any substantial amount
+of text.  A copy that is not ``Transparent'' is called ``Opaque''.
+
+Examples of suitable formats for Transparent copies include plain
+@sc{ascii} without markup, Texinfo input format, La@TeX{} input
+format, @acronym{SGML} or @acronym{XML} using a publicly available
+@acronym{DTD}, and standard-conforming simple @acronym{HTML},
+PostScript or @acronym{PDF} designed for human modification.  Examples
+of transparent image formats include @acronym{PNG}, @acronym{XCF} and
+@acronym{JPG}.  Opaque formats include proprietary formats that can be
+read and edited only by proprietary word processors, @acronym{SGML} or
+@acronym{XML} for which the @acronym{DTD} and/or processing tools are
+not generally available, and the machine-generated @acronym{HTML},
+PostScript or @acronym{PDF} produced by some word processors for
+output purposes only.
+
+The ``Title Page'' means, for a printed book, the title page itself,
+plus such following pages as are needed to hold, legibly, the material
+this License requires to appear in the title page.  For works in
+formats which do not have any title page as such, ``Title Page'' means
+the text near the most prominent appearance of the work's title,
+preceding the beginning of the body of the text.
+
+A section ``Entitled XYZ'' means a named subunit of the Document whose
+title either is precisely XYZ or contains XYZ in parentheses following
+text that translates XYZ in another language.  (Here XYZ stands for a
+specific section name mentioned below, such as ``Acknowledgements'',
+``Dedications'', ``Endorsements'', or ``History''.)  To ``Preserve the Title''
+of such a section when you modify the Document means that it remains a
+section ``Entitled XYZ'' according to this definition.
+
+The Document may include Warranty Disclaimers next to the notice which
+states that this License applies to the Document.  These Warranty
+Disclaimers are considered to be included by reference in this
+License, but only as regards disclaiming warranties: any other
+implication that these Warranty Disclaimers may have is void and has
+no effect on the meaning of this License.
+
+@item
+VERBATIM COPYING
+
+You may copy and distribute the Document in any medium, either
+commercially or noncommercially, provided that this License, the
+copyright notices, and the license notice saying this License applies
+to the Document are reproduced in all copies, and that you add no other
+conditions whatsoever to those of this License.  You may not use
+technical measures to obstruct or control the reading or further
+copying of the copies you make or distribute.  However, you may accept
+compensation in exchange for copies.  If you distribute a large enough
+number of copies you must also follow the conditions in section 3.
+
+You may also lend copies, under the same conditions stated above, and
+you may publicly display copies.
+
+@item
+COPYING IN QUANTITY
+
+If you publish printed copies (or copies in media that commonly have
+printed covers) of the Document, numbering more than 100, and the
+Document's license notice requires Cover Texts, you must enclose the
+copies in covers that carry, clearly and legibly, all these Cover
+Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
+the back cover.  Both covers must also clearly and legibly identify
+you as the publisher of these copies.  The front cover must present
+the full title with all words of the title equally prominent and
+visible.  You may add other material on the covers in addition.
+Copying with changes limited to the covers, as long as they preserve
+the title of the Document and satisfy these conditions, can be treated
+as verbatim copying in other respects.
+
+If the required texts for either cover are too voluminous to fit
+legibly, you should put the first ones listed (as many as fit
+reasonably) on the actual cover, and continue the rest onto adjacent
+pages.
+
+If you publish or distribute Opaque copies of the Document numbering
+more than 100, you must either include a machine-readable Transparent
+copy along with each Opaque copy, or state in or with each Opaque copy
+a computer-network location from which the general network-using
+public has access to download using public-standard network protocols
+a complete Transparent copy of the Document, free of added material.
+If you use the latter option, you must take reasonably prudent steps,
+when you begin distribution of Opaque copies in quantity, to ensure
+that this Transparent copy will remain thus accessible at the stated
+location until at least one year after the last time you distribute an
+Opaque copy (directly or through your agents or retailers) of that
+edition to the public.
+
+It is requested, but not required, that you contact the authors of the
+Document well before redistributing any large number of copies, to give
+them a chance to provide you with an updated version of the Document.
+
+@item
+MODIFICATIONS
+
+You may copy and distribute a Modified Version of the Document under
+the conditions of sections 2 and 3 above, provided that you release
+the Modified Version under precisely this License, with the Modified
+Version filling the role of the Document, thus licensing distribution
+and modification of the Modified Version to whoever possesses a copy
+of it.  In addition, you must do these things in the Modified Version:
+
+@enumerate A
+@item
+Use in the Title Page (and on the covers, if any) a title distinct
+from that of the Document, and from those of previous versions
+(which should, if there were any, be listed in the History section
+of the Document).  You may use the same title as a previous version
+if the original publisher of that version gives permission.
+
+@item
+List on the Title Page, as authors, one or more persons or entities
+responsible for authorship of the modifications in the Modified
+Version, together with at least five of the principal authors of the
+Document (all of its principal authors, if it has fewer than five),
+unless they release you from this requirement.
+
+@item
+State on the Title page the name of the publisher of the
+Modified Version, as the publisher.
+
+@item
+Preserve all the copyright notices of the Document.
+
+@item
+Add an appropriate copyright notice for your modifications
+adjacent to the other copyright notices.
+
+@item
+Include, immediately after the copyright notices, a license notice
+giving the public permission to use the Modified Version under the
+terms of this License, in the form shown in the Addendum below.
+
+@item
+Preserve in that license notice the full lists of Invariant Sections
+and required Cover Texts given in the Document's license notice.
+
+@item
+Include an unaltered copy of this License.
+
+@item
+Preserve the section Entitled ``History'', Preserve its Title, and add
+to it an item stating at least the title, year, new authors, and
+publisher of the Modified Version as given on the Title Page.  If
+there is no section Entitled ``History'' in the Document, create one
+stating the title, year, authors, and publisher of the Document as
+given on its Title Page, then add an item describing the Modified
+Version as stated in the previous sentence.
+
+@item
+Preserve the network location, if any, given in the Document for
+public access to a Transparent copy of the Document, and likewise
+the network locations given in the Document for previous versions
+it was based on.  These may be placed in the ``History'' section.
+You may omit a network location for a work that was published at
+least four years before the Document itself, or if the original
+publisher of the version it refers to gives permission.
+
+@item
+For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve
+the Title of the section, and preserve in the section all the
+substance and tone of each of the contributor acknowledgements and/or
+dedications given therein.
+
+@item
+Preserve all the Invariant Sections of the Document,
+unaltered in their text and in their titles.  Section numbers
+or the equivalent are not considered part of the section titles.
+
+@item
+Delete any section Entitled ``Endorsements''.  Such a section
+may not be included in the Modified Version.
+
+@item
+Do not retitle any existing section to be Entitled ``Endorsements'' or
+to conflict in title with any Invariant Section.
+
+@item
+Preserve any Warranty Disclaimers.
+@end enumerate
+
+If the Modified Version includes new front-matter sections or
+appendices that qualify as Secondary Sections and contain no material
+copied from the Document, you may at your option designate some or all
+of these sections as invariant.  To do this, add their titles to the
+list of Invariant Sections in the Modified Version's license notice.
+These titles must be distinct from any other section titles.
+
+You may add a section Entitled ``Endorsements'', provided it contains
+nothing but endorsements of your Modified Version by various
+parties---for example, statements of peer review or that the text has
+been approved by an organization as the authoritative definition of a
+standard.
+
+You may add a passage of up to five words as a Front-Cover Text, and a
+passage of up to 25 words as a Back-Cover Text, to the end of the list
+of Cover Texts in the Modified Version.  Only one passage of
+Front-Cover Text and one of Back-Cover Text may be added by (or
+through arrangements made by) any one entity.  If the Document already
+includes a cover text for the same cover, previously added by you or
+by arrangement made by the same entity you are acting on behalf of,
+you may not add another; but you may replace the old one, on explicit
+permission from the previous publisher that added the old one.
+
+The author(s) and publisher(s) of the Document do not by this License
+give permission to use their names for publicity for or to assert or
+imply endorsement of any Modified Version.
+
+@item
+COMBINING DOCUMENTS
+
+You may combine the Document with other documents released under this
+License, under the terms defined in section 4 above for modified
+versions, provided that you include in the combination all of the
+Invariant Sections of all of the original documents, unmodified, and
+list them all as Invariant Sections of your combined work in its
+license notice, and that you preserve all their Warranty Disclaimers.
+
+The combined work need only contain one copy of this License, and
+multiple identical Invariant Sections may be replaced with a single
+copy.  If there are multiple Invariant Sections with the same name but
+different contents, make the title of each such section unique by
+adding at the end of it, in parentheses, the name of the original
+author or publisher of that section if known, or else a unique number.
+Make the same adjustment to the section titles in the list of
+Invariant Sections in the license notice of the combined work.
+
+In the combination, you must combine any sections Entitled ``History''
+in the various original documents, forming one section Entitled
+``History''; likewise combine any sections Entitled ``Acknowledgements'',
+and any sections Entitled ``Dedications''.  You must delete all
+sections Entitled ``Endorsements.''
+
+@item
+COLLECTIONS OF DOCUMENTS
+
+You may make a collection consisting of the Document and other documents
+released under this License, and replace the individual copies of this
+License in the various documents with a single copy that is included in
+the collection, provided that you follow the rules of this License for
+verbatim copying of each of the documents in all other respects.
+
+You may extract a single document from such a collection, and distribute
+it individually under this License, provided you insert a copy of this
+License into the extracted document, and follow this License in all
+other respects regarding verbatim copying of that document.
+
+@item
+AGGREGATION WITH INDEPENDENT WORKS
+
+A compilation of the Document or its derivatives with other separate
+and independent documents or works, in or on a volume of a storage or
+distribution medium, is called an ``aggregate'' if the copyright
+resulting from the compilation is not used to limit the legal rights
+of the compilation's users beyond what the individual works permit.
+When the Document is included an aggregate, this License does not
+apply to the other works in the aggregate which are not themselves
+derivative works of the Document.
+
+If the Cover Text requirement of section 3 is applicable to these
+copies of the Document, then if the Document is less than one half of
+the entire aggregate, the Document's Cover Texts may be placed on
+covers that bracket the Document within the aggregate, or the
+electronic equivalent of covers if the Document is in electronic form.
+Otherwise they must appear on printed covers that bracket the whole
+aggregate.
+
+@item
+TRANSLATION
+
+Translation is considered a kind of modification, so you may
+distribute translations of the Document under the terms of section 4.
+Replacing Invariant Sections with translations requires special
+permission from their copyright holders, but you may include
+translations of some or all Invariant Sections in addition to the
+original versions of these Invariant Sections.  You may include a
+translation of this License, and all the license notices in the
+Document, and any Warrany Disclaimers, provided that you also include
+the original English version of this License and the original versions
+of those notices and disclaimers.  In case of a disagreement between
+the translation and the original version of this License or a notice
+or disclaimer, the original version will prevail.
+
+If a section in the Document is Entitled ``Acknowledgements'',
+``Dedications'', or ``History'', the requirement (section 4) to Preserve
+its Title (section 1) will typically require changing the actual
+title.
+
+@item
+TERMINATION
+
+You may not copy, modify, sublicense, or distribute the Document except
+as expressly provided for under this License.  Any other attempt to
+copy, modify, sublicense or distribute the Document is void, and will
+automatically terminate your rights under this License.  However,
+parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+@item
+FUTURE REVISIONS OF THIS LICENSE
+
+The Free Software Foundation may publish new, revised versions
+of the GNU Free Documentation License from time to time.  Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.  See
+@uref{http://www.gnu.org/copyleft/}.
+
+Each version of the License is given a distinguishing version number.
+If the Document specifies that a particular numbered version of this
+License ``or any later version'' applies to it, you have the option of
+following the terms and conditions either of that specified version or
+of any later version that has been published (not as a draft) by the
+Free Software Foundation.  If the Document does not specify a version
+number of this License, you may choose any version ever published (not
+as a draft) by the Free Software Foundation.
+@end enumerate
+
+@page
+@appendixsubsec ADDENDUM: How to use this License for your documents
+
+To use this License in a document you have written, include a copy of
+the License in the document and put the following copyright and
+license notices just after the title page:
+
+@smallexample
+@group
+  Copyright (C)  @var{year}  @var{your name}.
+  Permission is granted to copy, distribute and/or modify this document
+  under the terms of the GNU Free Documentation License, Version 1.2
+  or any later version published by the Free Software Foundation;
+  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
+  A copy of the license is included in the section entitled ``GNU
+  Free Documentation License''.
+@end group
+@end smallexample
+
+If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,
+replace the ``with...Texts.'' line with this:
+
+@smallexample
+@group
+    with the Invariant Sections being @var{list their titles}, with
+    the Front-Cover Texts being @var{list}, and with the Back-Cover Texts
+    being @var{list}.
+@end group
+@end smallexample
+
+If you have Invariant Sections without Cover Texts, or some other
+combination of the three, merge those two alternatives to suit the
+situation.
+
+If your document contains nontrivial examples of program code, we
+recommend releasing these examples in parallel under your choice of
+free software license, such as the GNU General Public License,
+to permit their use in free software.
+
+@c Local Variables:
+@c ispell-local-pdict: "ispell-dict"
+@c End:
+
diff --git a/apps/autodist/doc/mdate-sh b/apps/autodist/doc/mdate-sh
new file mode 100755 (executable)
index 0000000..b610b47
--- /dev/null
@@ -0,0 +1,133 @@
+#!/bin/sh
+# Get modification time of a file or directory and pretty-print it.
+# Copyright (C) 1995, 1996, 1997, 2003  Free Software Foundation, Inc.
+# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Prevent date giving response in another language.
+LANG=C
+export LANG
+LC_ALL=C
+export LC_ALL
+LC_TIME=C
+export LC_TIME
+
+save_arg1="$1"
+
+# Find out how to get the extended ls output of a file or directory.
+if ls -L /dev/null 1>/dev/null 2>&1; then
+  ls_command='ls -L -l -d'
+else
+  ls_command='ls -l -d'
+fi
+
+# A `ls -l' line looks as follows on OS/2.
+#  drwxrwx---        0 Aug 11  2001 foo
+# This differs from Unix, which adds ownership information.
+#  drwxrwx---   2 root  root      4096 Aug 11  2001 foo
+#
+# To find the date, we split the line on spaces and iterate on words
+# until we find a month.  This cannot work with files whose owner is a
+# user named `Jan', or `Feb', etc.  However, it's unlikely that `/'
+# will be owned by a user whose name is a month.  So we first look at
+# the extended ls output of the root directory to decide how many
+# words should be skipped to get the date.
+
+# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
+set - x`$ls_command /`
+
+# Find which argument is the month.
+month=
+command=
+until test $month
+do
+  shift
+  # Add another shift to the command.
+  command="$command shift;"
+  case $1 in
+    Jan) month=January; nummonth=1;;
+    Feb) month=February; nummonth=2;;
+    Mar) month=March; nummonth=3;;
+    Apr) month=April; nummonth=4;;
+    May) month=May; nummonth=5;;
+    Jun) month=June; nummonth=6;;
+    Jul) month=July; nummonth=7;;
+    Aug) month=August; nummonth=8;;
+    Sep) month=September; nummonth=9;;
+    Oct) month=October; nummonth=10;;
+    Nov) month=November; nummonth=11;;
+    Dec) month=December; nummonth=12;;
+  esac
+done
+
+# Get the extended ls output of the file or directory.
+set - x`eval "$ls_command \"\$save_arg1\""`
+
+# Remove all preceding arguments
+eval $command
+
+# Get the month.  Next argument is day, followed by the year or time.
+case $1 in
+  Jan) month=January; nummonth=1;;
+  Feb) month=February; nummonth=2;;
+  Mar) month=March; nummonth=3;;
+  Apr) month=April; nummonth=4;;
+  May) month=May; nummonth=5;;
+  Jun) month=June; nummonth=6;;
+  Jul) month=July; nummonth=7;;
+  Aug) month=August; nummonth=8;;
+  Sep) month=September; nummonth=9;;
+  Oct) month=October; nummonth=10;;
+  Nov) month=November; nummonth=11;;
+  Dec) month=December; nummonth=12;;
+esac
+
+day=$2
+
+# Here we have to deal with the problem that the ls output gives either
+# the time of day or the year.
+case $3 in
+  *:*) set `date`; eval year=\$$#
+       case $2 in
+        Jan) nummonthtod=1;;
+        Feb) nummonthtod=2;;
+        Mar) nummonthtod=3;;
+        Apr) nummonthtod=4;;
+        May) nummonthtod=5;;
+        Jun) nummonthtod=6;;
+        Jul) nummonthtod=7;;
+        Aug) nummonthtod=8;;
+        Sep) nummonthtod=9;;
+        Oct) nummonthtod=10;;
+        Nov) nummonthtod=11;;
+        Dec) nummonthtod=12;;
+       esac
+       # For the first six month of the year the time notation can also
+       # be used for files modified in the last year.
+       if (expr $nummonth \> $nummonthtod) > /dev/null;
+       then
+        year=`expr $year - 1`
+       fi;;
+  *) year=$3;;
+esac
+
+# The result.
+echo $day $month $year
diff --git a/apps/autodist/doc/texinfo.tex b/apps/autodist/doc/texinfo.tex
new file mode 100644 (file)
index 0000000..54c170d
--- /dev/null
@@ -0,0 +1,6740 @@
+% texinfo.tex -- TeX macros to handle Texinfo files.
+%
+% Load plain if necessary, i.e., if running under initex.
+\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
+%
+\def\texinfoversion{2003-10-16.18}
+%
+% Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
+% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+%
+% This texinfo.tex file is free software; you can redistribute it and/or
+% modify it under the terms of the GNU General Public License as
+% published by the Free Software Foundation; either version 2, or (at
+% your option) any later version.
+%
+% This texinfo.tex file 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
+% General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this texinfo.tex file; see the file COPYING.  If not, write
+% to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+% Boston, MA 02111-1307, USA.
+%
+% In other words, you are welcome to use, share and improve this program.
+% You are forbidden to forbid anyone else to use, share and improve
+% what you give them.   Help stamp out software-hoarding!
+%
+% Please try the latest version of texinfo.tex before submitting bug
+% reports; you can get the latest version from:
+%   ftp://ftp.gnu.org/gnu/texinfo/texinfo.tex
+%     (and all GNU mirrors, see http://www.gnu.org/order/ftp.html)
+%   ftp://tug.org/tex/texinfo.tex
+%     (and all CTAN mirrors, see http://www.ctan.org),
+%   and /home/gd/gnu/doc/texinfo.tex on the GNU machines.
+%
+% The GNU Texinfo home page is http://www.gnu.org/software/texinfo.
+%
+% The texinfo.tex in any given Texinfo distribution could well be out
+% of date, so if that's what you're using, please check.
+%
+% Send bug reports to bug-texinfo@gnu.org.  Please include including a
+% complete document in each bug report with which we can reproduce the
+% problem.  Patches are, of course, greatly appreciated.
+%
+% To process a Texinfo manual with TeX, it's most reliable to use the
+% texi2dvi shell script that comes with the distribution.  For a simple
+% manual foo.texi, however, you can get away with this:
+%   tex foo.texi
+%   texindex foo.??
+%   tex foo.texi
+%   tex foo.texi
+%   dvips foo.dvi -o  # or whatever; this makes foo.ps.
+% The extra TeX runs get the cross-reference information correct.
+% Sometimes one run after texindex suffices, and sometimes you need more
+% than two; texi2dvi does it as many times as necessary.
+%
+% It is possible to adapt texinfo.tex for other languages, to some
+% extent.  You can get the existing language-specific files from the
+% full Texinfo distribution.
+
+\message{Loading texinfo [version \texinfoversion]:}
+
+% If in a .fmt file, print the version number
+% and turn on active characters that we couldn't do earlier because
+% they might have appeared in the input file name.
+\everyjob{\message{[Texinfo version \texinfoversion]}%
+  \catcode`+=\active \catcode`\_=\active}
+
+\message{Basics,}
+\chardef\other=12
+
+% We never want plain's \outer definition of \+ in Texinfo.
+% For @tex, we can use \tabalign.
+\let\+ = \relax
+
+% Save some plain tex macros whose names we will redefine.
+\let\ptexb=\b
+\let\ptexbullet=\bullet
+\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv=\equiv
+\let\ptexexclam=\!
+\let\ptexgtr=>
+\let\ptexhat=^
+\let\ptexi=\i
+\let\ptexindent=\indent
+\let\ptexnoindent=\noindent
+\let\ptexlbrace=\{
+\let\ptexless=<
+\let\ptexplus=+
+\let\ptexrbrace=\}
+\let\ptexslash=\/
+\let\ptexstar=\*
+\let\ptext=\t
+
+% If this character appears in an error message or help string, it
+% starts a new line in the output.
+\newlinechar = `^^J
+
+% Set up fixed words for English if not already set.
+\ifx\putwordAppendix\undefined  \gdef\putwordAppendix{Appendix}\fi
+\ifx\putwordChapter\undefined   \gdef\putwordChapter{Chapter}\fi
+\ifx\putwordfile\undefined      \gdef\putwordfile{file}\fi
+\ifx\putwordin\undefined        \gdef\putwordin{in}\fi
+\ifx\putwordIndexIsEmpty\undefined     \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
+\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
+\ifx\putwordInfo\undefined      \gdef\putwordInfo{Info}\fi
+\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
+\ifx\putwordMethodon\undefined  \gdef\putwordMethodon{Method on}\fi
+\ifx\putwordNoTitle\undefined   \gdef\putwordNoTitle{No Title}\fi
+\ifx\putwordof\undefined        \gdef\putwordof{of}\fi
+\ifx\putwordon\undefined        \gdef\putwordon{on}\fi
+\ifx\putwordpage\undefined      \gdef\putwordpage{page}\fi
+\ifx\putwordsection\undefined   \gdef\putwordsection{section}\fi
+\ifx\putwordSection\undefined   \gdef\putwordSection{Section}\fi
+\ifx\putwordsee\undefined       \gdef\putwordsee{see}\fi
+\ifx\putwordSee\undefined       \gdef\putwordSee{See}\fi
+\ifx\putwordShortTOC\undefined  \gdef\putwordShortTOC{Short Contents}\fi
+\ifx\putwordTOC\undefined       \gdef\putwordTOC{Table of Contents}\fi
+%
+\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
+\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
+\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
+\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
+\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
+\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
+\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
+\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
+\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
+\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
+\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
+\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
+%
+\ifx\putwordDefmac\undefined    \gdef\putwordDefmac{Macro}\fi
+\ifx\putwordDefspec\undefined   \gdef\putwordDefspec{Special Form}\fi
+\ifx\putwordDefvar\undefined    \gdef\putwordDefvar{Variable}\fi
+\ifx\putwordDefopt\undefined    \gdef\putwordDefopt{User Option}\fi
+\ifx\putwordDeftypevar\undefined\gdef\putwordDeftypevar{Variable}\fi
+\ifx\putwordDeffunc\undefined   \gdef\putwordDeffunc{Function}\fi
+\ifx\putwordDeftypefun\undefined\gdef\putwordDeftypefun{Function}\fi
+
+% In some macros, we cannot use the `\? notation---the left quote is
+% in some cases the escape char.
+\chardef\colonChar = `\:
+\chardef\commaChar = `\,
+\chardef\dotChar   = `\.
+\chardef\equalChar = `\=
+\chardef\exclamChar= `\!
+\chardef\questChar = `\?
+\chardef\semiChar  = `\;
+\chardef\spaceChar = `\ %
+\chardef\underChar = `\_
+
+% Ignore a token.
+%
+\def\gobble#1{}
+
+% Hyphenation fixes.
+\hyphenation{ap-pen-dix}
+\hyphenation{eshell}
+\hyphenation{mini-buf-fer mini-buf-fers}
+\hyphenation{time-stamp}
+\hyphenation{white-space}
+
+% Margin to add to right of even pages, to left of odd pages.
+\newdimen\bindingoffset
+\newdimen\normaloffset
+\newdimen\pagewidth \newdimen\pageheight
+
+% Sometimes it is convenient to have everything in the transcript file
+% and nothing on the terminal.  We don't just call \tracingall here,
+% since that produces some useless output on the terminal.  We also make
+% some effort to order the tracing commands to reduce output in the log
+% file; cf. trace.sty in LaTeX.
+%
+\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
+\def\loggingall{%
+  \tracingstats2
+  \tracingpages1
+  \tracinglostchars2  % 2 gives us more in etex
+  \tracingparagraphs1
+  \tracingoutput1
+  \tracingmacros2
+  \tracingrestores1
+  \showboxbreadth\maxdimen \showboxdepth\maxdimen
+  \ifx\eTeXversion\undefined\else % etex gives us more logging
+    \tracingscantokens1
+    \tracingifs1
+    \tracinggroups1
+    \tracingnesting2
+    \tracingassigns1
+  \fi
+  \tracingcommands3  % 3 gives us more in etex
+  \errorcontextlines\maxdimen
+}%
+
+% add check for \lastpenalty to plain's definitions.  If the last thing
+% we did was a \nobreak, we don't want to insert more space.
+%
+\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
+  \removelastskip\penalty-50\smallskip\fi\fi}
+\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
+  \removelastskip\penalty-100\medskip\fi\fi}
+\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
+  \removelastskip\penalty-200\bigskip\fi\fi}
+
+% For @cropmarks command.
+% Do @cropmarks to get crop marks.
+%
+\newif\ifcropmarks
+\let\cropmarks = \cropmarkstrue
+%
+% Dimensions to add cropmarks at corners.
+% Added by P. A. MacKay, 12 Nov. 1986
+%
+\newdimen\outerhsize \newdimen\outervsize % set by the paper size routines
+\newdimen\cornerlong  \cornerlong=1pc
+\newdimen\cornerthick \cornerthick=.3pt
+\newdimen\topandbottommargin \topandbottommargin=.75in
+
+% Main output routine.
+\chardef\PAGE = 255
+\output = {\onepageout{\pagecontents\PAGE}}
+
+\newbox\headlinebox
+\newbox\footlinebox
+
+% \onepageout takes a vbox as an argument.  Note that \pagecontents
+% does insertions, but you have to call it yourself.
+\def\onepageout#1{%
+  \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+  %
+  \ifodd\pageno  \advance\hoffset by \bindingoffset
+  \else \advance\hoffset by -\bindingoffset\fi
+  %
+  % Do this outside of the \shipout so @code etc. will be expanded in
+  % the headline as they should be, not taken literally (outputting ''code).
+  \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+  \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+  %
+  {%
+    % Have to do this stuff outside the \shipout because we want it to
+    % take effect in \write's, yet the group defined by the \vbox ends
+    % before the \shipout runs.
+    %
+    \escapechar = `\\     % use backslash in output files.
+    \indexdummies         % don't expand commands in the output.
+    \normalturnoffactive  % \ in index entries must not stay \, e.g., if
+                   % the page break happens to be in the middle of an example.
+    \shipout\vbox{%
+      % Do this early so pdf references go to the beginning of the page.
+      \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
+      %
+      \ifcropmarks \vbox to \outervsize\bgroup
+        \hsize = \outerhsize
+        \vskip-\topandbottommargin
+        \vtop to0pt{%
+          \line{\ewtop\hfil\ewtop}%
+          \nointerlineskip
+          \line{%
+            \vbox{\moveleft\cornerthick\nstop}%
+            \hfill
+            \vbox{\moveright\cornerthick\nstop}%
+          }%
+          \vss}%
+        \vskip\topandbottommargin
+        \line\bgroup
+          \hfil % center the page within the outer (page) hsize.
+          \ifodd\pageno\hskip\bindingoffset\fi
+          \vbox\bgroup
+      \fi
+      %
+      \unvbox\headlinebox
+      \pagebody{#1}%
+      \ifdim\ht\footlinebox > 0pt
+        % Only leave this space if the footline is nonempty.
+        % (We lessened \vsize for it in \oddfootingxxx.)
+        % The \baselineskip=24pt in plain's \makefootline has no effect.
+        \vskip 2\baselineskip
+        \unvbox\footlinebox
+      \fi
+      %
+      \ifcropmarks
+          \egroup % end of \vbox\bgroup
+        \hfil\egroup % end of (centering) \line\bgroup
+        \vskip\topandbottommargin plus1fill minus1fill
+        \boxmaxdepth = \cornerthick
+        \vbox to0pt{\vss
+          \line{%
+            \vbox{\moveleft\cornerthick\nsbot}%
+            \hfill
+            \vbox{\moveright\cornerthick\nsbot}%
+          }%
+          \nointerlineskip
+          \line{\ewbot\hfil\ewbot}%
+        }%
+      \egroup % \vbox from first cropmarks clause
+      \fi
+    }% end of \shipout\vbox
+  }% end of group with \normalturnoffactive
+  \advancepageno
+  \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
+
+\newinsert\margin \dimen\margin=\maxdimen
+
+\def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}}
+{\catcode`\@ =11
+\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
+% marginal hacks, juha@viisa.uucp (Juha Takala)
+\ifvoid\margin\else % marginal info is present
+  \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
+\dimen@=\dp#1 \unvbox#1
+\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
+\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
+}
+
+% Here are the rules for the cropmarks.  Note that they are
+% offset so that the space between them is truly \outerhsize or \outervsize
+% (P. A. MacKay, 12 November, 1986)
+%
+\def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong}
+\def\nstop{\vbox
+  {\hrule height\cornerthick depth\cornerlong width\cornerthick}}
+\def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong}
+\def\nsbot{\vbox
+  {\hrule height\cornerlong depth\cornerthick width\cornerthick}}
+
+% Parse an argument, then pass it to #1.  The argument is the rest of
+% the input line (except we remove a trailing comment).  #1 should be a
+% macro which expects an ordinary undelimited TeX argument.
+%
+\def\parsearg#1{%
+  \let\next = #1%
+  \begingroup
+    \obeylines
+    \futurelet\temp\parseargx
+}
+
+% If the next token is an obeyed space (from an @example environment or
+% the like), remove it and recurse.  Otherwise, we're done.
+\def\parseargx{%
+  % \obeyedspace is defined far below, after the definition of \sepspaces.
+  \ifx\obeyedspace\temp
+    \expandafter\parseargdiscardspace
+  \else
+    \expandafter\parseargline
+  \fi
+}
+
+% Remove a single space (as the delimiter token to the macro call).
+{\obeyspaces %
+ \gdef\parseargdiscardspace {\futurelet\temp\parseargx}}
+
+{\obeylines %
+  \gdef\parseargline#1^^M{%
+    \endgroup % End of the group started in \parsearg.
+    %
+    % First remove any @c comment, then any @comment.
+    % Result of each macro is put in \toks0.
+    \argremovec #1\c\relax %
+    \expandafter\argremovecomment \the\toks0 \comment\relax %
+    %
+    % Call the caller's macro, saved as \next in \parsearg.
+    \expandafter\next\expandafter{\the\toks0}%
+  }%
+}
+
+% Since all \c{,omment} does is throw away the argument, we can let TeX
+% do that for us.  The \relax here is matched by the \relax in the call
+% in \parseargline; it could be more or less anything, its purpose is
+% just to delimit the argument to the \c.
+\def\argremovec#1\c#2\relax{\toks0 = {#1}}
+\def\argremovecomment#1\comment#2\relax{\toks0 = {#1}}
+
+% \argremovec{,omment} might leave us with trailing spaces, though; e.g.,
+%    @end itemize  @c foo
+% will have two active spaces as part of the argument with the
+% `itemize'.  Here we remove all active spaces from #1, and assign the
+% result to \toks0.
+%
+% This loses if there are any *other* active characters besides spaces
+% in the argument -- _ ^ +, for example -- since they get expanded.
+% Fortunately, Texinfo does not define any such commands.  (If it ever
+% does, the catcode of the characters in questionwill have to be changed
+% here.)  But this means we cannot call \removeactivespaces as part of
+% \argremovec{,omment}, since @c uses \parsearg, and thus the argument
+% that \parsearg gets might well have any character at all in it.
+%
+\def\removeactivespaces#1{%
+  \begingroup
+    \ignoreactivespaces
+    \edef\temp{#1}%
+    \global\toks0 = \expandafter{\temp}%
+  \endgroup
+}
+
+% Change the active space to expand to nothing.
+%
+\begingroup
+  \obeyspaces
+  \gdef\ignoreactivespaces{\obeyspaces\let =\empty}
+\endgroup
+
+
+\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
+
+%% These are used to keep @begin/@end levels from running away
+%% Call \inENV within environments (after a \begingroup)
+\newif\ifENV \ENVfalse \def\inENV{\ifENV\relax\else\ENVtrue\fi}
+\def\ENVcheck{%
+\ifENV\errmessage{Still within an environment; press RETURN to continue}
+\endgroup\fi} % This is not perfect, but it should reduce lossage
+
+% @begin foo  is the same as @foo, for now.
+\newhelp\EMsimple{Press RETURN to continue.}
+
+\outer\def\begin{\parsearg\beginxxx}
+
+\def\beginxxx #1{%
+\expandafter\ifx\csname #1\endcsname\relax
+{\errhelp=\EMsimple \errmessage{Undefined command @begin #1}}\else
+\csname #1\endcsname\fi}
+
+% @end foo executes the definition of \Efoo.
+%
+\def\end{\parsearg\endxxx}
+\def\endxxx #1{%
+  \removeactivespaces{#1}%
+  \edef\endthing{\the\toks0}%
+  %
+  \expandafter\ifx\csname E\endthing\endcsname\relax
+    \expandafter\ifx\csname \endthing\endcsname\relax
+      % There's no \foo, i.e., no ``environment'' foo.
+      \errhelp = \EMsimple
+      \errmessage{Undefined command `@end \endthing'}%
+    \else
+      \unmatchedenderror\endthing
+    \fi
+  \else
+    % Everything's ok; the right environment has been started.
+    \csname E\endthing\endcsname
+  \fi
+}
+
+% There is an environment #1, but it hasn't been started.  Give an error.
+%
+\def\unmatchedenderror#1{%
+  \errhelp = \EMsimple
+  \errmessage{This `@end #1' doesn't have a matching `@#1'}%
+}
+
+% Define the control sequence \E#1 to give an unmatched @end error.
+%
+\def\defineunmatchedend#1{%
+  \expandafter\def\csname E#1\endcsname{\unmatchedenderror{#1}}%
+}
+
+
+%% Simple single-character @ commands
+
+% @@ prints an @
+% Kludge this until the fonts are right (grr).
+\def\@{{\tt\char64}}
+
+% This is turned off because it was never documented
+% and you can use @w{...} around a quote to suppress ligatures.
+%% Define @` and @' to be the same as ` and '
+%% but suppressing ligatures.
+%\def\`{{`}}
+%\def\'{{'}}
+
+% Used to generate quoted braces.
+\def\mylbrace {{\tt\char123}}
+\def\myrbrace {{\tt\char125}}
+\let\{=\mylbrace
+\let\}=\myrbrace
+\begingroup
+  % Definitions to produce \{ and \} commands for indices,
+  % and @{ and @} for the aux file.
+  \catcode`\{ = \other \catcode`\} = \other
+  \catcode`\[ = 1 \catcode`\] = 2
+  \catcode`\! = 0 \catcode`\\ = \other
+  !gdef!lbracecmd[\{]%
+  !gdef!rbracecmd[\}]%
+  !gdef!lbraceatcmd[@{]%
+  !gdef!rbraceatcmd[@}]%
+!endgroup
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown
+% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+  \def\temp{#1}%
+  \ifx\temp\imacro \ptexi
+  \else\ifx\temp\jmacro \j
+  \else \errmessage{@dotless can be used only with i or j}%
+  \fi\fi
+}
+
+% Be sure we're in horizontal mode when doing a tie, since we make space
+% equivalent to this in @example-like environments. Otherwise, a space
+% at the beginning of a line will start with \penalty -- and
+% since \penalty is valid in vertical mode, we'd end up putting the
+% penalty on the vertical list instead of in the new paragraph.
+{\catcode`@ = 11
+ % Avoid using \@M directly, because that causes trouble
+ % if the definition is written into an index file.
+ \global\let\tiepenalty = \@M
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
+}
+
+% @: forces normal size whitespace following.
+\def\:{\spacefactor=1000 }
+
+% @* forces a line break.
+\def\*{\hfil\break\hbox{}\ignorespaces}
+
+% @/ allows a line break.
+\let\/=\allowbreak
+
+% @. is an end-of-sentence period.
+\def\.{.\spacefactor=3000 }
+
+% @! is an end-of-sentence bang.
+\def\!{!\spacefactor=3000 }
+
+% @? is an end-of-sentence query.
+\def\?{?\spacefactor=3000 }
+
+% @w prevents a word break.  Without the \leavevmode, @w at the
+% beginning of a paragraph, when TeX is still in vertical mode, would
+% produce a whole line of output instead of starting the paragraph.
+\def\w#1{\leavevmode\hbox{#1}}
+
+% @group ... @end group forces ... to be all on one page, by enclosing
+% it in a TeX vbox.  We use \vtop instead of \vbox to construct the box
+% to keep its height that of a normal line.  According to the rules for
+% \topskip (p.114 of the TeXbook), the glue inserted is
+% max (\topskip - \ht (first item), 0).  If that height is large,
+% therefore, no glue is inserted, and the space between the headline and
+% the text is small, which looks bad.
+%
+% Another complication is that the group might be very large.  This can
+% cause the glue on the previous page to be unduly stretched, because it
+% does not have much material.  In this case, it's better to add an
+% explicit \vfill so that the extra space is at the bottom.  The
+% threshold for doing this is if the group is more than \vfilllimit
+% percent of a page (\vfilllimit can be changed inside of @tex).
+%
+\newbox\groupbox
+\def\vfilllimit{0.7}
+%
+\def\group{\begingroup
+  \ifnum\catcode13=\active \else
+    \errhelp = \groupinvalidhelp
+    \errmessage{@group invalid in context where filling is enabled}%
+  \fi
+  %
+  % The \vtop we start below produces a box with normal height and large
+  % depth; thus, TeX puts \baselineskip glue before it, and (when the
+  % next line of text is done) \lineskip glue after it.  (See p.82 of
+  % the TeXbook.)  Thus, space below is not quite equal to space
+  % above.  But it's pretty close.
+  \def\Egroup{%
+    \egroup           % End the \vtop.
+    % \dimen0 is the vertical size of the group's box.
+    \dimen0 = \ht\groupbox  \advance\dimen0 by \dp\groupbox
+    % \dimen2 is how much space is left on the page (more or less).
+    \dimen2 = \pageheight   \advance\dimen2 by -\pagetotal
+    % if the group doesn't fit on the current page, and it's a big big
+    % group, force a page break.
+    \ifdim \dimen0 > \dimen2
+      \ifdim \pagetotal < \vfilllimit\pageheight
+        \page
+      \fi
+    \fi
+    \copy\groupbox
+    \endgroup         % End the \group.
+  }%
+  %
+  \setbox\groupbox = \vtop\bgroup
+    % We have to put a strut on the last line in case the @group is in
+    % the midst of an example, rather than completely enclosing it.
+    % Otherwise, the interline space between the last line of the group
+    % and the first line afterwards is too small.  But we can't put the
+    % strut in \Egroup, since there it would be on a line by itself.
+    % Hence this just inserts a strut at the beginning of each line.
+    \everypar = {\strut}%
+    %
+    % Since we have a strut on every line, we don't need any of TeX's
+    % normal interline spacing.
+    \offinterlineskip
+    %
+    % OK, but now we have to do something about blank
+    % lines in the input in @example-like environments, which normally
+    % just turn into \lisppar, which will insert no space now that we've
+    % turned off the interline space.  Simplest is to make them be an
+    % empty paragraph.
+    \ifx\par\lisppar
+      \edef\par{\leavevmode \par}%
+      %
+      % Reset ^^M's definition to new definition of \par.
+      \obeylines
+    \fi
+    %
+    % Do @comment since we are called inside an environment such as
+    % @example, where each end-of-line in the input causes an
+    % end-of-line in the output.  We don't want the end-of-line after
+    % the `@group' to put extra space in the output.  Since @group
+    % should appear on a line by itself (according to the Texinfo
+    % manual), we don't worry about eating any user text.
+    \comment
+}
+%
+% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
+% message, so this ends up printing `@group can only ...'.
+%
+\newhelp\groupinvalidhelp{%
+group can only be used in environments such as @example,^^J%
+where each line of input produces a line of output.}
+
+% @need space-in-mils
+% forces a page break if there is not space-in-mils remaining.
+
+\newdimen\mil  \mil=0.001in
+
+\def\need{\parsearg\needx}
+
+% Old definition--didn't work.
+%\def\needx #1{\par %
+%% This method tries to make TeX break the page naturally
+%% if the depth of the box does not fit.
+%{\baselineskip=0pt%
+%\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak
+%\prevdepth=-1000pt
+%}}
+
+\def\needx#1{%
+  % Ensure vertical mode, so we don't make a big box in the middle of a
+  % paragraph.
+  \par
+  %
+  % If the @need value is less than one line space, it's useless.
+  \dimen0 = #1\mil
+  \dimen2 = \ht\strutbox
+  \advance\dimen2 by \dp\strutbox
+  \ifdim\dimen0 > \dimen2
+    %
+    % Do a \strut just to make the height of this box be normal, so the
+    % normal leading is inserted relative to the preceding line.
+    % And a page break here is fine.
+    \vtop to #1\mil{\strut\vfil}%
+    %
+    % TeX does not even consider page breaks if a penalty added to the
+    % main vertical list is 10000 or more.  But in order to see if the
+    % empty box we just added fits on the page, we must make it consider
+    % page breaks.  On the other hand, we don't want to actually break the
+    % page after the empty box.  So we use a penalty of 9999.
+    %
+    % There is an extremely small chance that TeX will actually break the
+    % page at this \penalty, if there are no other feasible breakpoints in
+    % sight.  (If the user is using lots of big @group commands, which
+    % almost-but-not-quite fill up a page, TeX will have a hard time doing
+    % good page breaking, for example.)  However, I could not construct an
+    % example where a page broke at this \penalty; if it happens in a real
+    % document, then we can reconsider our strategy.
+    \penalty9999
+    %
+    % Back up by the size of the box, whether we did a page break or not.
+    \kern -#1\mil
+    %
+    % Do not allow a page break right after this kern.
+    \nobreak
+  \fi
+}
+
+% @br   forces paragraph break
+
+\let\br = \par
+
+% @dots{} output an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in a typewriter
+% font as three actual period characters.
+%
+\def\dots{%
+  \leavevmode
+  \hbox to 1.5em{%
+    \hskip 0pt plus 0.25fil minus 0.25fil
+    .\hss.\hss.%
+    \hskip 0pt plus 0.5fil minus 0.5fil
+  }%
+}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+  \leavevmode
+  \hbox to 2em{%
+    \hskip 0pt plus 0.25fil minus 0.25fil
+    .\hss.\hss.\hss.%
+    \hskip 0pt plus 0.5fil minus 0.5fil
+  }%
+  \spacefactor=3000
+}
+
+% @page forces the start of a new page.
+%
+\def\page{\par\vfill\supereject}
+
+% @exdent text....
+% outputs text on separate line in roman font, starting at standard page margin
+
+% This records the amount of indent in the innermost environment.
+% That's how much \exdent should take out.
+\newskip\exdentamount
+
+% This defn is used inside fill environments such as @defun.
+\def\exdent{\parsearg\exdentyyy}
+\def\exdentyyy #1{{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}}
+
+% This defn is used inside nofill environments such as @example.
+\def\nofillexdent{\parsearg\nofillexdentyyy}
+\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
+\leftline{\hskip\leftskip{\rm#1}}}}
+
+% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
+% paragraph.  For more general purposes, use the \margin insertion
+% class.  WHICH is `l' or `r'.
+%
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+%
+\def\doinmargin#1#2{\strut\vadjust{%
+  \nobreak
+  \kern-\strutdepth
+  \vtop to \strutdepth{%
+    \baselineskip=\strutdepth
+    \vss
+    % if you have multiple lines of stuff to put here, you'll need to
+    % make the vbox yourself of the appropriate size.
+    \ifx#1l%
+      \llap{\ignorespaces #2\hskip\inmarginspacing}%
+    \else
+      \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
+    \fi
+    \null
+  }%
+}}
+\def\inleftmargin{\doinmargin l}
+\def\inrightmargin{\doinmargin r}
+%
+% @inmargin{TEXT [, RIGHT-TEXT]}
+% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
+% else use TEXT for both).
+%
+\def\inmargin#1{\parseinmargin #1,,\finish}
+\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
+  \setbox0 = \hbox{\ignorespaces #2}%
+  \ifdim\wd0 > 0pt
+    \def\lefttext{#1}%  have both texts
+    \def\righttext{#2}%
+  \else
+    \def\lefttext{#1}%  have only one text
+    \def\righttext{#1}%
+  \fi
+  %
+  \ifodd\pageno
+    \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
+  \else
+    \def\temp{\inleftmargin\lefttext}%
+  \fi
+  \temp
+}
+
+% @include file    insert text of that file as input.
+% Allow normal characters that  we make active in the argument (a file name).
+\def\include{\begingroup
+  \catcode`\\=\other
+  \catcode`~=\other
+  \catcode`^=\other
+  \catcode`_=\other
+  \catcode`|=\other
+  \catcode`<=\other
+  \catcode`>=\other
+  \catcode`+=\other
+  \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+  % Read the included file in a group so nested @include's work.
+  \def\thisfile{#1}%
+  \let\value=\expandablevalue
+  \input\thisfile
+\endgroup}
+
+\def\thisfile{}
+
+% @center line
+% outputs that line, centered.
+%
+\def\center{\parsearg\docenter}
+\def\docenter#1{{%
+  \ifhmode \hfil\break \fi
+  \advance\hsize by -\leftskip
+  \advance\hsize by -\rightskip
+  \line{\hfil \ignorespaces#1\unskip \hfil}%
+  \ifhmode \break \fi
+}}
+
+% @sp n   outputs n lines of vertical space
+
+\def\sp{\parsearg\spxxx}
+\def\spxxx #1{\vskip #1\baselineskip}
+
+% @comment ...line which is ignored...
+% @c is the same as @comment
+% @ignore ... @end ignore  is another way to write a comment
+
+\def\comment{\begingroup \catcode`\^^M=\other%
+\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
+\commentxxx}
+{\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}}
+
+\let\c=\comment
+
+% @paragraphindent NCHARS
+% We'll use ems for NCHARS, close enough.
+% NCHARS can also be the word `asis' or `none'.
+% We cannot feasibly implement @paragraphindent asis, though.
+%
+\def\asisword{asis} % no translation, these are keywords
+\def\noneword{none}
+%
+\def\paragraphindent{\parsearg\doparagraphindent}
+\def\doparagraphindent#1{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \defaultparindent = 0pt
+    \else
+      \defaultparindent = #1em
+    \fi
+  \fi
+  \parindent = \defaultparindent
+}
+
+% @exampleindent NCHARS
+% We'll use ems for NCHARS like @paragraphindent.
+% It seems @exampleindent asis isn't necessary, but
+% I preserve it to make it similar to @paragraphindent.
+\def\exampleindent{\parsearg\doexampleindent}
+\def\doexampleindent#1{%
+  \def\temp{#1}%
+  \ifx\temp\asisword
+  \else
+    \ifx\temp\noneword
+      \lispnarrowing = 0pt
+    \else
+      \lispnarrowing = #1em
+    \fi
+  \fi
+}
+
+% @firstparagraphindent WORD
+% If WORD is `none', then suppress indentation of the first paragraph
+% after a section heading.  If WORD is `insert', then do indent at such
+% paragraphs.
+%
+% The paragraph indentation is suppressed or not by calling
+% \suppressfirstparagraphindent, which the sectioning commands do.
+% We switch the definition of this back and forth according to WORD.
+% By default, we suppress indentation.
+%
+\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
+\newdimen\currentparindent
+%
+\def\insertword{insert}
+%
+\def\firstparagraphindent{\parsearg\dofirstparagraphindent}
+\def\dofirstparagraphindent#1{%
+  \def\temp{#1}%
+  \ifx\temp\noneword
+    \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
+  \else\ifx\temp\insertword
+    \let\suppressfirstparagraphindent = \relax
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @firstparagraphindent option `\temp'}%
+  \fi\fi
+}
+
+% Here is how we actually suppress indentation.  Redefine \everypar to
+% \kern backwards by \parindent, and then reset itself to empty.
+%
+% We also make \indent itself not actually do anything until the next
+% paragraph.
+%
+\gdef\dosuppressfirstparagraphindent{%
+  \gdef\indent{%
+    \restorefirstparagraphindent
+    \indent
+  }%
+  \gdef\noindent{%
+    \restorefirstparagraphindent
+    \noindent
+  }%
+  \global\everypar = {%
+    \kern -\parindent
+    \restorefirstparagraphindent
+  }%
+}
+
+\gdef\restorefirstparagraphindent{%
+  \global \let \indent = \ptexindent
+  \global \let \noindent = \ptexnoindent
+  \global \everypar = {}%
+}
+
+
+% @asis just yields its argument.  Used with @table, for example.
+%
+\def\asis#1{#1}
+
+% @math outputs its argument in math mode.
+% We don't use $'s directly in the definition of \math because we need
+% to set catcodes according to plain TeX first, to allow for subscripts,
+% superscripts, special math chars, etc.
+%
+\let\implicitmath = $%$ font-lock fix
+%
+% One complication: _ usually means subscripts, but it could also mean
+% an actual _ character, as in @math{@var{some_variable} + 1}.  So make
+% _ within @math be active (mathcode "8000), and distinguish by seeing
+% if the current family is \slfam, which is what @var uses.
+%
+{\catcode\underChar = \active
+\gdef\mathunderscore{%
+  \catcode\underChar=\active
+  \def_{\ifnum\fam=\slfam \_\else\sb\fi}%
+}}
+%
+% Another complication: we want \\ (and @\) to output a \ character.
+% FYI, plain.tex uses \\ as a temporary control sequence (why?), but
+% this is not advertised and we don't care.  Texinfo does not
+% otherwise define @\.
+%
+% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
+\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
+%
+\def\math{%
+  \tex
+  \mathcode`\_="8000 \mathunderscore
+  \let\\ = \mathbackslash
+  \mathactive
+  \implicitmath\finishmath}
+\def\finishmath#1{#1\implicitmath\Etex}
+
+% Some active characters (such as <) are spaced differently in math.
+% We have to reset their definitions in case the @math was an
+% argument to a command which set the catcodes (such as @item or @section).
+%
+{
+  \catcode`^ = \active
+  \catcode`< = \active
+  \catcode`> = \active
+  \catcode`+ = \active
+  \gdef\mathactive{%
+    \let^ = \ptexhat
+    \let< = \ptexless
+    \let> = \ptexgtr
+    \let+ = \ptexplus
+  }
+}
+
+% @bullet and @minus need the same treatment as @math, just above.
+\def\bullet{\implicitmath\ptexbullet\implicitmath}
+\def\minus{\implicitmath-\implicitmath}
+
+% @refill is a no-op.
+\let\refill=\relax
+
+% If working on a large document in chapters, it is convenient to
+% be able to disable indexing, cross-referencing, and contents, for test runs.
+% This is done with @novalidate (before @setfilename).
+%
+\newif\iflinks \linkstrue % by default we want the aux files.
+\let\novalidate = \linksfalse
+
+% @setfilename is done at the beginning of every texinfo file.
+% So open here the files we need to have open while reading the input.
+% This makes it possible to make a .fmt file for texinfo.
+\def\setfilename{%
+   \iflinks
+     \readauxfile
+   \fi % \openindices needs to do some work in any case.
+   \openindices
+   \fixbackslash  % Turn off hack to swallow `\input texinfo'.
+   \global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+   %
+   % If texinfo.cnf is present on the system, read it.
+   % Useful for site-wide @afourpaper, etc.
+   % Just to be on the safe side, close the input stream before the \input.
+   \openin 1 texinfo.cnf
+   \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi
+   \closein1
+   \temp
+   %
+   \comment % Ignore the actual filename.
+}
+
+% Called from \setfilename.
+%
+\def\openindices{%
+  \newindex{cp}%
+  \newcodeindex{fn}%
+  \newcodeindex{vr}%
+  \newcodeindex{tp}%
+  \newcodeindex{ky}%
+  \newcodeindex{pg}%
+}
+
+% @bye.
+\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
+
+
+\message{pdf,}
+% adobe `portable' document format
+\newcount\tempnum
+\newcount\lnkcount
+\newtoks\filename
+\newcount\filenamelength
+\newcount\pgn
+\newtoks\toksA
+\newtoks\toksB
+\newtoks\toksC
+\newtoks\toksD
+\newbox\boxA
+\newcount\countA
+\newif\ifpdf
+\newif\ifpdfmakepagedest
+
+\ifx\pdfoutput\undefined
+  \pdffalse
+  \let\pdfmkdest = \gobble
+  \let\pdfurl = \gobble
+  \let\endlink = \relax
+  \let\linkcolor = \relax
+  \let\pdfmakeoutlines = \relax
+\else
+  \pdftrue
+  \pdfoutput = 1
+  \input pdfcolor
+  \pdfcatalog{/PageMode /UseOutlines}%
+  \def\dopdfimage#1#2#3{%
+    \def\imagewidth{#2}%
+    \def\imageheight{#3}%
+    % without \immediate, pdftex seg faults when the same image is
+    % included twice.  (Version 3.14159-pre-1.0-unofficial-20010704.)
+    \ifnum\pdftexversion < 14
+      \immediate\pdfimage
+    \else
+      \immediate\pdfximage
+    \fi
+      \ifx\empty\imagewidth\else width \imagewidth \fi
+      \ifx\empty\imageheight\else height \imageheight \fi
+      \ifnum\pdftexversion<13
+         #1.pdf%
+       \else
+         {#1.pdf}%
+       \fi
+    \ifnum\pdftexversion < 14 \else
+      \pdfrefximage \pdflastximage
+    \fi}
+  \def\pdfmkdest#1{{%
+    % We have to set dummies so commands such as @code in a section title
+    % aren't expanded.
+    \atdummies
+    \normalturnoffactive
+    \pdfdest name{#1} xyz%
+  }}
+  \def\pdfmkpgn#1{#1}
+  \let\linkcolor = \Blue  % was Cyan, but that seems light?
+  \def\endlink{\Black\pdfendlink}
+  % Adding outlines to PDF; macros for calculating structure of outlines
+  % come from Petr Olsak
+  \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
+    \else \csname#1\endcsname \fi}
+  \def\advancenumber#1{\tempnum=\expnumber{#1}\relax
+    \advance\tempnum by 1
+    \expandafter\xdef\csname#1\endcsname{\the\tempnum}}
+  %
+  % #1 is the section text.  #2 is the pdf expression for the number
+  % of subentries (or empty, for subsubsections).  #3 is the node
+  % text, which might be empty if this toc entry had no
+  % corresponding node.  #4 is the page number.
+  % 
+  \def\dopdfoutline#1#2#3#4{%
+    % Generate a link to the node text if that exists; else, use the
+    % page number.  We could generate a destination for the section
+    % text in the case where a section has no node, but it doesn't
+    % seem worthwhile, since most documents are normally structured.
+    \def\pdfoutlinedest{#3}%
+    \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}\fi
+    %
+    \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}%
+  }
+  %
+  \def\pdfmakeoutlines{%
+    \openin 1 \jobname.toc
+    \ifeof 1\else\begingroup
+      \closein 1
+      % Thanh's hack / proper braces in bookmarks
+      \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace
+      \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace
+      %
+      % Read toc silently, to get counts of subentries for \pdfoutline.
+      \def\numchapentry##1##2##3##4{\def\thischapnum{##2}}%
+      \def\numsecentry##1##2##3##4{%
+        \def\thissecnum{##2}%
+        \advancenumber{chap\thischapnum}}%
+      \def\numsubsecentry##1##2##3##4{%
+        \def\thissubsecnum{##2}%
+        \advancenumber{sec\thissecnum}}%
+      \def\numsubsubsecentry##1##2##3##4{\advancenumber{subsec\thissubsecnum}}%
+      %
+      % use \def rather than \let here because we redefine \chapentry et
+      % al. a second time, below.
+      \def\appentry{\numchapentry}%
+      \def\appsecentry{\numsecentry}%
+      \def\appsubsecentry{\numsubsecentry}%
+      \def\appsubsubsecentry{\numsubsubsecentry}%
+      \def\unnchapentry{\numchapentry}%
+      \def\unnsecentry{\numsecentry}%
+      \def\unnsubsecentry{\numsubsecentry}%
+      \def\unnsubsubsecentry{\numsubsubsecentry}%
+      \input \jobname.toc
+      %
+      % Read toc second time, this time actually producing the outlines.
+      % The `-' means take the \expnumber as the absolute number of
+      % subentries, which we calculated on our first read of the .toc above.
+      % 
+      % We use the node names as the destinations.
+      \def\numchapentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
+      \def\numsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
+      \def\numsubsecentry##1##2##3##4{%
+        \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}%
+      \def\numsubsubsecentry##1##2##3##4{% count is always zero
+        \dopdfoutline{##1}{}{##3}{##4}}%
+      %
+      % Make special characters normal for writing to the pdf file.
+      \indexnofonts
+      \turnoffactive
+      \input \jobname.toc
+    \endgroup\fi
+  }
+  %
+  \def\makelinks #1,{%
+    \def\params{#1}\def\E{END}%
+    \ifx\params\E
+      \let\nextmakelinks=\relax
+    \else
+      \let\nextmakelinks=\makelinks
+      \ifnum\lnkcount>0,\fi
+      \picknum{#1}%
+      \startlink attr{/Border [0 0 0]}
+        goto name{\pdfmkpgn{\the\pgn}}%
+      \linkcolor #1%
+      \advance\lnkcount by 1%
+      \endlink
+    \fi
+    \nextmakelinks
+  }
+  \def\picknum#1{\expandafter\pn#1}
+  \def\pn#1{%
+    \def\p{#1}%
+    \ifx\p\lbrace
+      \let\nextpn=\ppn
+    \else
+      \let\nextpn=\ppnn
+      \def\first{#1}
+    \fi
+    \nextpn
+  }
+  \def\ppn#1{\pgn=#1\gobble}
+  \def\ppnn{\pgn=\first}
+  \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,}
+  \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+  \def\skipspaces#1{\def\PP{#1}\def\D{|}%
+    \ifx\PP\D\let\nextsp\relax
+    \else\let\nextsp\skipspaces
+      \ifx\p\space\else\addtokens{\filename}{\PP}%
+        \advance\filenamelength by 1
+      \fi
+    \fi
+    \nextsp}
+  \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax}
+  \ifnum\pdftexversion < 14
+    \let \startlink \pdfannotlink
+  \else
+    \let \startlink \pdfstartlink
+  \fi
+  \def\pdfurl#1{%
+    \begingroup
+      \normalturnoffactive\def\@{@}%
+      \let\value=\expandablevalue
+      \leavevmode\Red
+      \startlink attr{/Border [0 0 0]}%
+        user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
+        % #1
+    \endgroup}
+  \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
+  \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
+  \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
+  \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
+  \def\maketoks{%
+    \expandafter\poptoks\the\toksA|ENDTOKS|
+    \ifx\first0\adn0
+    \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
+    \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
+    \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
+    \else
+      \ifnum0=\countA\else\makelink\fi
+      \ifx\first.\let\next=\done\else
+        \let\next=\maketoks
+        \addtokens{\toksB}{\the\toksD}
+        \ifx\first,\addtokens{\toksB}{\space}\fi
+      \fi
+    \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+    \next}
+  \def\makelink{\addtokens{\toksB}%
+    {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
+  \def\pdflink#1{%
+    \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
+    \linkcolor #1\endlink}
+  \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
+\fi % \ifx\pdfoutput
+
+
+\message{fonts,}
+% Font-change commands.
+
+% Texinfo sort of supports the sans serif font style, which plain TeX does not.
+% So we set up a \sf analogous to plain's \rm, etc.
+\newfam\sffam
+\def\sf{\fam=\sffam \tensf}
+\let\li = \sf % Sometimes we call it \li, not \sf.
+
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+% Default leading.
+\newdimen\textleading  \textleading = 13.2pt
+
+% Set the baselineskip to #1, and the lineskip and strut size
+% correspondingly.  There is no deep meaning behind these magic numbers
+% used as factors; they just match (closely enough) what Knuth defined.
+%
+\def\lineskipfactor{.08333}
+\def\strutheightpercent{.70833}
+\def\strutdepthpercent {.29167}
+%
+\def\setleading#1{%
+  \normalbaselineskip = #1\relax
+  \normallineskip = \lineskipfactor\normalbaselineskip
+  \normalbaselines
+  \setbox\strutbox =\hbox{%
+    \vrule width0pt height\strutheightpercent\baselineskip
+                    depth \strutdepthpercent \baselineskip
+  }%
+}
+
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
+
+% Use cm as the default font prefix.
+% To specify the font prefix, you must define \fontprefix
+% before you read in texinfo.tex.
+\ifx\fontprefix\undefined
+\def\fontprefix{cm}
+\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx}               %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
+
+\newcount\mainmagstep
+\ifx\bigger\relax
+  % not really supported.
+  \mainmagstep=\magstep1
+  \setfont\textrm\rmshape{12}{1000}
+  \setfont\texttt\ttshape{12}{1000}
+\else
+  \mainmagstep=\magstephalf
+  \setfont\textrm\rmshape{10}{\mainmagstep}
+  \setfont\texttt\ttshape{10}{\mainmagstep}
+\fi
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
+\font\texti=cmmi10 scaled \mainmagstep
+\font\textsy=cmsy10 scaled \mainmagstep
+
+% A few fonts for @defun, etc.
+\setfont\defbf\bfshape{10}{\magstep1}
+\setfont\deftt\ttshape{10}{\magstep1}
+\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
+
+% Fonts for indices, footnotes, small examples (9pt).
+\setfont\smallrm\rmshape{9}{1000}
+\setfont\smalltt\ttshape{9}{1000}
+\setfont\smallbf\bfshape{10}{900}
+\setfont\smallit\itshape{9}{1000}
+\setfont\smallsl\slshape{9}{1000}
+\setfont\smallsf\sfshape{9}{1000}
+\setfont\smallsc\scshape{10}{900}
+\setfont\smallttsl\ttslshape{10}{900}
+\font\smalli=cmmi9
+\font\smallsy=cmsy9
+
+% Fonts for small examples (8pt).
+\setfont\smallerrm\rmshape{8}{1000}
+\setfont\smallertt\ttshape{8}{1000}
+\setfont\smallerbf\bfshape{10}{800}
+\setfont\smallerit\itshape{8}{1000}
+\setfont\smallersl\slshape{8}{1000}
+\setfont\smallersf\sfshape{8}{1000}
+\setfont\smallersc\scshape{10}{800}
+\setfont\smallerttsl\ttslshape{10}{800}
+\font\smalleri=cmmi8
+\font\smallersy=cmsy8
+
+% Fonts for title page:
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\setfont\titleit\itbshape{10}{\magstep4}
+\setfont\titlesl\slbshape{10}{\magstep4}
+\setfont\titlett\ttbshape{12}{\magstep3}
+\setfont\titlettsl\ttslshape{10}{\magstep4}
+\setfont\titlesf\sfbshape{17}{\magstep1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+\def\authortt{\sectt}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{17}{1000}
+\let\chapbf=\chaprm
+\setfont\chapsc\scbshape{10}{\magstep3}
+\font\chapi=cmmi12 scaled \magstep2
+\font\chapsy=cmsy10 scaled \magstep3
+
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
+\font\seci=cmmi12 scaled \magstep1
+\font\secsy=cmsy10 scaled \magstep2
+
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{1315}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{\magstep1}
+\font\sseci=cmmi12 scaled \magstephalf
+\font\ssecsy=cmsy10 scaled 1315
+% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
+% but that is not a standard magnification.
+
+% In order for the font changes to affect most math symbols and letters,
+% we have to define the \textfont of the standard families.  Since
+% texinfo doesn't allow for producing subscripts and superscripts except
+% in the main text, we don't bother to reset \scriptfont and
+% \scriptscriptfont (which would also require loading a lot more fonts).
+%
+\def\resetmathfonts{%
+  \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy
+  \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf
+  \textfont\ttfam=\tentt \textfont\sffam=\tensf
+}
+
+% The font-changing commands redefine the meanings of \tenSTYLE, instead
+% of just \STYLE.  We do this so that font changes will continue to work
+% in math mode, where it is the current \fam that is relevant in most
+% cases, not the current font.  Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example.  By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
+\def\textfonts{%
+  \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
+  \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
+  \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl
+  \resetmathfonts \setleading{\textleading}}
+\def\titlefonts{%
+  \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+  \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+  \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+  \let\tenttsl=\titlettsl
+  \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #1}}
+\def\chapfonts{%
+  \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
+  \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
+  \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+  \resetmathfonts \setleading{19pt}}
+\def\secfonts{%
+  \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
+  \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
+  \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl
+  \resetmathfonts \setleading{16pt}}
+\def\subsecfonts{%
+  \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
+  \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
+  \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl
+  \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
+\def\smallfonts{%
+  \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl
+  \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc
+  \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy
+  \let\tenttsl=\smallttsl
+  \resetmathfonts \setleading{10.5pt}}
+\def\smallerfonts{%
+  \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl
+  \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc
+  \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy
+  \let\tenttsl=\smallerttsl
+  \resetmathfonts \setleading{9.5pt}}
+
+% Set the fonts to use with the @small... environments.
+\let\smallexamplefonts = \smallfonts
+
+% About \smallexamplefonts.  If we use \smallfonts (9pt), @smallexample
+% can fit this many characters:
+%   8.5x11=86   smallbook=72  a4=90  a5=69
+% If we use \smallerfonts (8pt), then we can fit this many characters:
+%   8.5x11=90+  smallbook=80  a4=90+  a5=77
+% For me, subjectively, the few extra characters that fit aren't worth
+% the additional smallness of 8pt.  So I'm making the default 9pt.
+%
+% By the way, for comparison, here's what fits with @example (10pt):
+%   8.5x11=71  smallbook=60  a4=75  a5=58
+%
+% I wish we used A4 paper on this side of the Atlantic.
+%
+% --karl, 24jan03.
+
+
+% Set up the default fonts, so we can use them for creating boxes.
+%
+\textfonts
+
+% Define these so they can be easily changed for other fonts.
+\def\angleleft{$\langle$}
+\def\angleright{$\rangle$}
+
+% Count depth in font-changes, for error checks
+\newcount\fontdepth \fontdepth=0
+
+% Fonts for short table of contents.
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bfshape{10}{\magstep1}  % no cmb12
+\setfont\shortcontsl\slshape{12}{1000}
+\setfont\shortconttt\ttshape{12}{1000}
+
+%% Add scribe-like font environments, plus @l for inline lisp (usually sans
+%% serif) and @ii for TeX italic
+
+% \smartitalic{ARG} outputs arg in italics, followed by an italic correction
+% unless the following character is such as not to need one.
+\def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else
+                    \ptexslash\fi\fi\fi}
+\def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx}
+\def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx}
+
+\let\i=\smartitalic
+\let\var=\smartslanted
+\let\dfn=\smartslanted
+\let\emph=\smartitalic
+\let\cite=\smartslanted
+
+\def\b#1{{\bf #1}}
+\let\strong=\b
+
+% We can't just use \exhyphenpenalty, because that only has effect at
+% the end of a paragraph.  Restore normal hyphenation at the end of the
+% group within which \nohyphenation is presumably called.
+%
+\def\nohyphenation{\hyphenchar\font = -1  \aftergroup\restorehyphenation}
+\def\restorehyphenation{\hyphenchar\font = `- }
+
+% Set sfcode to normal for the chars that usually have another value.
+% Can't use plain's \frenchspacing because it uses the `\x notation, and
+% sometimes \x has an active definition that messes things up.
+%
+\catcode`@=11
+  \def\frenchspacing{%
+    \sfcode\dotChar  =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m
+    \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m
+  }
+\catcode`@=\other
+
+\def\t#1{%
+  {\tt \rawbackslash \frenchspacing #1}%
+  \null
+}
+\let\ttfont=\t
+\def\samp#1{`\tclose{#1}'\null}
+\setfont\keyrm\rmshape{8}{1000}
+\font\keysy=cmsy9
+\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
+  \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+    \vbox{\hrule\kern-0.4pt
+     \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+    \kern-0.4pt\hrule}%
+  \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
+\def\tclose#1{%
+  {%
+    % Change normal interword space to be same as for the current font.
+    \spaceskip = \fontdimen2\font
+    %
+    % Switch to typewriter.
+    \tt
+    %
+    % But `\ ' produces the large typewriter interword space.
+    \def\ {{\spaceskip = 0pt{} }}%
+    %
+    % Turn off hyphenation.
+    \nohyphenation
+    %
+    \rawbackslash
+    \frenchspacing
+    #1%
+  }%
+  \null
+}
+
+% We *must* turn on hyphenation at `-' and `_' in \code.
+% Otherwise, it is too hard to avoid overfull hboxes
+% in the Emacs manual, the Library manual, etc.
+
+% Unfortunately, TeX uses one parameter (\hyphenchar) to control
+% both hyphenation at - and hyphenation within words.
+% We must therefore turn them both off (\tclose does that)
+% and arrange explicitly to hyphenate at a dash.
+%  -- rms.
+{
+  \catcode`\-=\active
+  \catcode`\_=\active
+  %
+  \global\def\code{\begingroup
+    \catcode`\-=\active \let-\codedash
+    \catcode`\_=\active \let_\codeunder
+    \codex
+  }
+  %
+  % If we end up with any active - characters when handling the index,
+  % just treat them as a normal -.
+  \global\def\indexbreaks{\catcode`\-=\active \let-\realdash}
+}
+
+\def\realdash{-}
+\def\codedash{-\discretionary{}{}{}}
+\def\codeunder{%
+  % this is all so @math{@code{var_name}+1} can work.  In math mode, _
+  % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
+  % will therefore expand the active definition of _, which is us
+  % (inside @code that is), therefore an endless loop.
+  \ifusingtt{\ifmmode
+               \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
+             \else\normalunderscore \fi
+             \discretionary{}{}{}}%
+            {\_}%
+}
+\def\codex #1{\tclose{#1}\endgroup}
+
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+%   `example' (@kbd uses ttsl only inside of @example and friends),
+%   or `code' (@kbd uses normal tty font always).
+\def\kbdinputstyle{\parsearg\kbdinputstylexxx}
+\def\kbdinputstylexxx#1{%
+  \def\arg{#1}%
+  \ifx\arg\worddistinct
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+  \else\ifx\arg\wordexample
+    \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+  \else\ifx\arg\wordcode
+    \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+  \else
+    \errhelp = \EMsimple
+    \errmessage{Unknown @kbdinputstyle option `\arg'}%
+  \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is `distinct.'
+\kbdinputstyle distinct
+
+\def\xkey{\key}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% For @url, @env, @command quotes seem unnecessary, so use \code.
+\let\url=\code
+\let\env=\code
+\let\command=\code
+
+% @uref (abbreviation for `urlref') takes an optional (comma-separated)
+% second argument specifying the text to display and an optional third
+% arg as text to display instead of (rather than in addition to) the url
+% itself.  First (mandatory) arg is the url.  Perhaps eventually put in
+% a hypertex \special here.
+%
+\def\uref#1{\douref #1,,,\finish}
+\def\douref#1,#2,#3,#4\finish{\begingroup
+  \unsepspaces
+  \pdfurl{#1}%
+  \setbox0 = \hbox{\ignorespaces #3}%
+  \ifdim\wd0 > 0pt
+    \unhbox0 % third arg given, show only that
+  \else
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0 > 0pt
+      \ifpdf
+        \unhbox0             % PDF: 2nd arg given, show only it
+      \else
+        \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url
+      \fi
+    \else
+      \code{#1}% only url given, so show it
+    \fi
+  \fi
+  \endlink
+\endgroup}
+
+% rms does not like angle brackets --karl, 17may97.
+% So now @email is just like @uref, unless we are pdf.
+%
+%\def\email#1{\angleleft{\tt #1}\angleright}
+\ifpdf
+  \def\email#1{\doemail#1,,\finish}
+  \def\doemail#1,#2,#3\finish{\begingroup
+    \unsepspaces
+    \pdfurl{mailto:#1}%
+    \setbox0 = \hbox{\ignorespaces #2}%
+    \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
+    \endlink
+  \endgroup}
+\else
+  \let\email=\uref
+\fi
+
+% Check if we are currently using a typewriter font.  Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
+
+% Typeset a dimension, e.g., `in' or `pt'.  The only reason for the
+% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
+%
+\def\dmn#1{\thinspace #1}
+
+\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
+
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find.  We need it for
+% Polish suppressed-l.  --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
+
+% Explicit font changes: @r, @sc, undocumented @ii.
+\def\r#1{{\rm #1}}              % roman font
+\def\sc#1{{\smallcaps#1}}       % smallcaps font
+\def\ii#1{{\it #1}}             % italic font
+
+% @acronym downcases the argument and prints in smallcaps.
+\def\acronym#1{{\smallcaps \lowercase{#1}}}
+
+% @pounds{} is a sterling sign.
+\def\pounds{{\it\$}}
+
+% @registeredsymbol - R in a circle.  For now, only works in text size;
+% we'd have to redo the font mechanism to change the \scriptstyle and
+% \scriptscriptstyle font sizes to make it look right in headings.
+% Adapted from the plain.tex definition of \copyright.
+%
+\def\registeredsymbol{%
+  $^{{\ooalign{\hfil\raise.07ex\hbox{$\scriptstyle\rm R$}\hfil\crcr\Orb}}%
+    }$%
+}
+
+
+\message{page headings,}
+
+\newskip\titlepagetopglue \titlepagetopglue = 1.5in
+\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
+
+% First the title page.  Must do @settitle before @titlepage.
+\newif\ifseenauthor
+\newif\iffinishedtitlepage
+
+% Do an implicit @contents or @shortcontents after @end titlepage if the
+% user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage.
+%
+\newif\ifsetcontentsaftertitlepage
+ \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue
+\newif\ifsetshortcontentsaftertitlepage
+ \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue
+
+\def\shorttitlepage{\parsearg\shorttitlepagezzz}
+\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
+        \endgroup\page\hbox{}\page}
+
+\def\titlepage{\begingroup \parindent=0pt \textfonts
+   \let\subtitlerm=\tenrm
+   \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}%
+   %
+   \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines
+                   \let\tt=\authortt}%
+   %
+   % Leave some space at the very top of the page.
+   \vglue\titlepagetopglue
+   %
+   % Now you can print the title using @title.
+   \def\title{\parsearg\titlezzz}%
+   \def\titlezzz##1{\leftline{\titlefonts\rm ##1}
+                    % print a rule at the page bottom also.
+                    \finishedtitlepagefalse
+                    \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+   % No rule at page bottom unless we print one at the top with @title.
+   \finishedtitlepagetrue
+   %
+   % Now you can put text using @subtitle.
+   \def\subtitle{\parsearg\subtitlezzz}%
+   \def\subtitlezzz##1{{\subtitlefont \rightline{##1}}}%
+   %
+   % @author should come last, but may come many times.
+   \def\author{\parsearg\authorzzz}%
+   \def\authorzzz##1{\ifseenauthor\else\vskip 0pt plus 1filll\seenauthortrue\fi
+      {\authorfont \leftline{##1}}}%
+   %
+   % Most title ``pages'' are actually two pages long, with space
+   % at the top of the second.  We don't want the ragged left on the second.
+   \let\oldpage = \page
+   \def\page{%
+      \iffinishedtitlepage\else
+         \finishtitlepage
+      \fi
+      \oldpage
+      \let\page = \oldpage
+      \hbox{}}%
+%   \def\page{\oldpage \hbox{}}
+}
+
+\def\Etitlepage{%
+   \iffinishedtitlepage\else
+      \finishtitlepage
+   \fi
+   % It is important to do the page break before ending the group,
+   % because the headline and footline are only empty inside the group.
+   % If we use the new definition of \page, we always get a blank page
+   % after the title page, which we certainly don't want.
+   \oldpage
+   \endgroup
+   %
+   % Need this before the \...aftertitlepage checks so that if they are
+   % in effect the toc pages will come out with page numbers.
+   \HEADINGSon
+   %
+   % If they want short, they certainly want long too.
+   \ifsetshortcontentsaftertitlepage
+     \shortcontents
+     \contents
+     \global\let\shortcontents = \relax
+     \global\let\contents = \relax
+   \fi
+   %
+   \ifsetcontentsaftertitlepage
+     \contents
+     \global\let\contents = \relax
+     \global\let\shortcontents = \relax
+   \fi
+}
+
+\def\finishtitlepage{%
+   \vskip4pt \hrule height 2pt width \hsize
+   \vskip\titlepagebottomglue
+   \finishedtitlepagetrue
+}
+
+%%% Set up page headings and footings.
+
+\let\thispage=\folio
+
+\newtoks\evenheadline    % headline on even pages
+\newtoks\oddheadline     % headline on odd pages
+\newtoks\evenfootline    % footline on even pages
+\newtoks\oddfootline     % footline on odd pages
+
+% Now make Tex use those variables
+\headline={{\textfonts\rm \ifodd\pageno \the\oddheadline
+                            \else \the\evenheadline \fi}}
+\footline={{\textfonts\rm \ifodd\pageno \the\oddfootline
+                            \else \the\evenfootline \fi}\HEADINGShook}
+\let\HEADINGShook=\relax
+
+% Commands to set those variables.
+% For example, this is what  @headings on  does
+% @evenheading @thistitle|@thispage|@thischapter
+% @oddheading @thischapter|@thispage|@thistitle
+% @evenfooting @thisfile||
+% @oddfooting ||@thisfile
+
+\def\evenheading{\parsearg\evenheadingxxx}
+\def\oddheading{\parsearg\oddheadingxxx}
+\def\everyheading{\parsearg\everyheadingxxx}
+
+\def\evenfooting{\parsearg\evenfootingxxx}
+\def\oddfooting{\parsearg\oddfootingxxx}
+\def\everyfooting{\parsearg\everyfootingxxx}
+
+{\catcode`\@=0 %
+
+\gdef\evenheadingxxx #1{\evenheadingyyy #1@|@|@|@|\finish}
+\gdef\evenheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddheadingxxx #1{\oddheadingyyy #1@|@|@|@|\finish}
+\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
+\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
+
+\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
+\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
+\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+
+\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
+\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
+  \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+  %
+  % Leave some space for the footline.  Hopefully ok to assume
+  % @evenfooting will not be used by itself.
+  \global\advance\pageheight by -\baselineskip
+  \global\advance\vsize by -\baselineskip
+}
+
+\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}}
+%
+}% unbind the catcode of @.
+
+% @headings double      turns headings on for double-sided printing.
+% @headings single      turns headings on for single-sided printing.
+% @headings off         turns them off.
+% @headings on          same as @headings double, retained for compatibility.
+% @headings after       turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
+% @headings singleafter turns on single-sided headings after this page.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
+
+\def\headings #1 {\csname HEADINGS#1\endcsname}
+
+\def\HEADINGSoff{
+\global\evenheadline={\hfil} \global\evenfootline={\hfil}
+\global\oddheadline={\hfil} \global\oddfootline={\hfil}}
+\HEADINGSoff
+% When we turn headings on, set the page number to 1.
+% For double-sided printing, put current file name in lower left corner,
+% chapter name on inside top of right hand pages, document
+% title on inside top of left hand pages, and page numbers on outside top
+% edge of all pages.
+\def\HEADINGSdouble{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+\let\contentsalignmacro = \chappager
+
+% For single-sided printing, chapter title goes across top left of page,
+% page number on top right.
+\def\HEADINGSsingle{
+\global\pageno=1
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+\def\HEADINGSon{\HEADINGSdouble}
+
+\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
+\let\HEADINGSdoubleafter=\HEADINGSafter
+\def\HEADINGSdoublex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\folio\hfil\thistitle}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
+}
+
+\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
+\def\HEADINGSsinglex{%
+\global\evenfootline={\hfil}
+\global\oddfootline={\hfil}
+\global\evenheadline={\line{\thischapter\hfil\folio}}
+\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
+}
+
+% Subroutines used in generating headings
+% This produces Day Month Year style of output.
+% Only define if not already defined, in case a txi-??.tex file has set
+% up a different format (e.g., txi-cs.tex does this).
+\ifx\today\undefined
+\def\today{%
+  \number\day\space
+  \ifcase\month
+  \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
+  \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
+  \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
+  \fi
+  \space\number\year}
+\fi
+
+% @settitle line...  specifies the title of the document, for headings.
+% It generates no output of its own.
+\def\thistitle{\putwordNoTitle}
+\def\settitle{\parsearg\settitlezzz}
+\def\settitlezzz #1{\gdef\thistitle{#1}}
+
+
+\message{tables,}
+% Tables -- @table, @ftable, @vtable, @item(x), @kitem(x), @xitem(x).
+
+% default indentation of table text
+\newdimen\tableindent \tableindent=.8in
+% default indentation of @itemize and @enumerate text
+\newdimen\itemindent  \itemindent=.3in
+% margin between end of table item and start of table text.
+\newdimen\itemmargin  \itemmargin=.1in
+
+% used internally for \itemindent minus \itemmargin
+\newdimen\itemmax
+
+% Note @table, @vtable, and @vtable define @item, @itemx, etc., with
+% these defs.
+% They also define \itemindex
+% to index the item name in whatever manner is desired (perhaps none).
+
+\newif\ifitemxneedsnegativevskip
+
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
+
+\def\internalBitem{\smallbreak \parsearg\itemzzz}
+\def\internalBitemx{\itemxpar \parsearg\itemzzz}
+
+\def\internalBxitem "#1"{\def\xitemsubtopix{#1} \smallbreak \parsearg\xitemzzz}
+\def\internalBxitemx "#1"{\def\xitemsubtopix{#1} \itemxpar \parsearg\xitemzzz}
+
+\def\internalBkitem{\smallbreak \parsearg\kitemzzz}
+\def\internalBkitemx{\itemxpar \parsearg\kitemzzz}
+
+\def\kitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \lastfunction}}%
+                 \itemzzz {#1}}
+
+\def\xitemzzz #1{\dosubind {kw}{\code{#1}}{for {\bf \xitemsubtopic}}%
+                 \itemzzz {#1}}
+
+\def\itemzzz #1{\begingroup %
+  \advance\hsize by -\rightskip
+  \advance\hsize by -\tableindent
+  \setbox0=\hbox{\itemfont{#1}}%
+  \itemindex{#1}%
+  \nobreak % This prevents a break before @itemx.
+  %
+  % If the item text does not fit in the space we have, put it on a line
+  % by itself, and do not allow a page break either before or after that
+  % line.  We do not start a paragraph here because then if the next
+  % command is, e.g., @kindex, the whatsit would get put into the
+  % horizontal list on a line by itself, resulting in extra blank space.
+  \ifdim \wd0>\itemmax
+    %
+    % Make this a paragraph so we get the \parskip glue and wrapping,
+    % but leave it ragged-right.
+    \begingroup
+      \advance\leftskip by-\tableindent
+      \advance\hsize by\tableindent
+      \advance\rightskip by0pt plus1fil
+      \leavevmode\unhbox0\par
+    \endgroup
+    %
+    % We're going to be starting a paragraph, but we don't want the
+    % \parskip glue -- logically it's part of the @item we just started.
+    \nobreak \vskip-\parskip
+    %
+    % Stop a page break at the \parskip glue coming up.  (Unfortunately
+    % we can't prevent a possible page break at the following
+    % \baselineskip glue.)  However, if what follows is an environment
+    % such as @example, there will be no \parskip glue; then
+    % the negative vskip we just would cause the example and the item to
+    % crash together.  So we use this bizarre value of 10001 as a signal
+    % to \aboveenvbreak to insert \parskip glue after all.
+    % (Possibly there are other commands that could be followed by
+    % @example which need the same treatment, but not section titles; or
+    % maybe section titles are the only special case and they should be
+    % penalty 10001...)
+    \penalty 10001
+    \endgroup
+    \itemxneedsnegativevskipfalse
+  \else
+    % The item text fits into the space.  Start a paragraph, so that the
+    % following text (if any) will end up on the same line.
+    \noindent
+    % Do this with kerns and \unhbox so that if there is a footnote in
+    % the item text, it can migrate to the main vertical list and
+    % eventually be printed.
+    \nobreak\kern-\tableindent
+    \dimen0 = \itemmax  \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
+    \unhbox0
+    \nobreak\kern\dimen0
+    \endgroup
+    \itemxneedsnegativevskiptrue
+  \fi
+}
+
+\def\item{\errmessage{@item while not in a table}}
+\def\itemx{\errmessage{@itemx while not in a table}}
+\def\kitem{\errmessage{@kitem while not in a table}}
+\def\kitemx{\errmessage{@kitemx while not in a table}}
+\def\xitem{\errmessage{@xitem while not in a table}}
+\def\xitemx{\errmessage{@xitemx while not in a table}}
+
+% Contains a kludge to get @end[description] to work.
+\def\description{\tablez{\dontindex}{1}{}{}{}{}}
+
+% @table, @ftable, @vtable.
+\def\table{\begingroup\inENV\obeylines\obeyspaces\tablex}
+{\obeylines\obeyspaces%
+\gdef\tablex #1^^M{%
+\tabley\dontindex#1        \endtabley}}
+
+\def\ftable{\begingroup\inENV\obeylines\obeyspaces\ftablex}
+{\obeylines\obeyspaces%
+\gdef\ftablex #1^^M{%
+\tabley\fnitemindex#1        \endtabley
+\def\Eftable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\vtable{\begingroup\inENV\obeylines\obeyspaces\vtablex}
+{\obeylines\obeyspaces%
+\gdef\vtablex #1^^M{%
+\tabley\vritemindex#1        \endtabley
+\def\Evtable{\endgraf\afterenvbreak\endgroup}%
+\let\Etable=\relax}}
+
+\def\dontindex #1{}
+\def\fnitemindex #1{\doind {fn}{\code{#1}}}%
+\def\vritemindex #1{\doind {vr}{\code{#1}}}%
+
+{\obeyspaces %
+\gdef\tabley#1#2 #3 #4 #5 #6 #7\endtabley{\endgroup%
+\tablez{#1}{#2}{#3}{#4}{#5}{#6}}}
+
+\def\tablez #1#2#3#4#5#6{%
+\aboveenvbreak %
+\begingroup %
+\def\Edescription{\Etable}% Necessary kludge.
+\let\itemindex=#1%
+\ifnum 0#3>0 \advance \leftskip by #3\mil \fi %
+\ifnum 0#4>0 \tableindent=#4\mil \fi %
+\ifnum 0#5>0 \advance \rightskip by #5\mil \fi %
+\def\itemfont{#2}%
+\itemmax=\tableindent %
+\advance \itemmax by -\itemmargin %
+\advance \leftskip by \tableindent %
+\exdentamount=\tableindent
+\parindent = 0pt
+\parskip = \smallskipamount
+\ifdim \parskip=0pt \parskip=2pt \fi%
+\def\Etable{\endgraf\afterenvbreak\endgroup}%
+\let\item = \internalBitem %
+\let\itemx = \internalBitemx %
+\let\kitem = \internalBkitem %
+\let\kitemx = \internalBkitemx %
+\let\xitem = \internalBxitem %
+\let\xitemx = \internalBxitemx %
+}
+
+% This is the counter used by @enumerate, which is really @itemize
+
+\newcount \itemno
+
+\def\itemize{\parsearg\itemizezzz}
+
+\def\itemizezzz #1{%
+  \begingroup % ended by the @end itemize
+  \itemizey {#1}{\Eitemize}
+}
+
+\def\itemizey#1#2{%
+  \aboveenvbreak
+  \itemmax=\itemindent
+  \advance\itemmax by -\itemmargin
+  \advance\leftskip by \itemindent
+  \exdentamount=\itemindent
+  \parindent=0pt
+  \parskip=\smallskipamount
+  \ifdim\parskip=0pt \parskip=2pt \fi
+  \def#2{\endgraf\afterenvbreak\endgroup}%
+  \def\itemcontents{#1}%
+  % @itemize with no arg is equivalent to @itemize @bullet.
+  \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
+  \let\item=\itemizeitem
+}
+
+% \splitoff TOKENS\endmark defines \first to be the first token in
+% TOKENS, and \rest to be the remainder.
+%
+\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
+
+% Allow an optional argument of an uppercase letter, lowercase letter,
+% or number, to specify the first label in the enumerated list.  No
+% argument is the same as `1'.
+%
+\def\enumerate{\parsearg\enumeratezzz}
+\def\enumeratezzz #1{\enumeratey #1  \endenumeratey}
+\def\enumeratey #1 #2\endenumeratey{%
+  \begingroup % ended by the @end enumerate
+  %
+  % If we were given no argument, pretend we were given `1'.
+  \def\thearg{#1}%
+  \ifx\thearg\empty \def\thearg{1}\fi
+  %
+  % Detect if the argument is a single token.  If so, it might be a
+  % letter.  Otherwise, the only valid thing it can be is a number.
+  % (We will always have one token, because of the test we just made.
+  % This is a good thing, since \splitoff doesn't work given nothing at
+  % all -- the first parameter is undelimited.)
+  \expandafter\splitoff\thearg\endmark
+  \ifx\rest\empty
+    % Only one token in the argument.  It could still be anything.
+    % A ``lowercase letter'' is one whose \lccode is nonzero.
+    % An ``uppercase letter'' is one whose \lccode is both nonzero, and
+    %   not equal to itself.
+    % Otherwise, we assume it's a number.
+    %
+    % We need the \relax at the end of the \ifnum lines to stop TeX from
+    % continuing to look for a <number>.
+    %
+    \ifnum\lccode\expandafter`\thearg=0\relax
+      \numericenumerate % a number (we hope)
+    \else
+      % It's a letter.
+      \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
+        \lowercaseenumerate % lowercase letter
+      \else
+        \uppercaseenumerate % uppercase letter
+      \fi
+    \fi
+  \else
+    % Multiple tokens in the argument.  We hope it's a number.
+    \numericenumerate
+  \fi
+}
+
+% An @enumerate whose labels are integers.  The starting integer is
+% given in \thearg.
+%
+\def\numericenumerate{%
+  \itemno = \thearg
+  \startenumeration{\the\itemno}%
+}
+
+% The starting (lowercase) letter is in \thearg.
+\def\lowercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more lowercase letters in @enumerate; get a bigger
+                  alphabet}%
+    \fi
+    \char\lccode\itemno
+  }%
+}
+
+% The starting (uppercase) letter is in \thearg.
+\def\uppercaseenumerate{%
+  \itemno = \expandafter`\thearg
+  \startenumeration{%
+    % Be sure we're not beyond the end of the alphabet.
+    \ifnum\itemno=0
+      \errmessage{No more uppercase letters in @enumerate; get a bigger
+                  alphabet}
+    \fi
+    \char\uccode\itemno
+  }%
+}
+
+% Call itemizey, adding a period to the first argument and supplying the
+% common last two arguments.  Also subtract one from the initial value in
+% \itemno, since @item increments \itemno.
+%
+\def\startenumeration#1{%
+  \advance\itemno by -1
+  \itemizey{#1.}\Eenumerate\flushcr
+}
+
+% @alphaenumerate and @capsenumerate are abbreviations for giving an arg
+% to @enumerate.
+%
+\def\alphaenumerate{\enumerate{a}}
+\def\capsenumerate{\enumerate{A}}
+\def\Ealphaenumerate{\Eenumerate}
+\def\Ecapsenumerate{\Eenumerate}
+
+% Definition of @item while inside @itemize.
+
+\def\itemizeitem{%
+\advance\itemno by 1
+{\let\par=\endgraf \smallbreak}%
+\ifhmode \errmessage{In hmode at itemizeitem}\fi
+{\parskip=0in \hskip 0pt
+\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
+\vadjust{\penalty 1200}}%
+\flushcr}
+
+% @multitable macros
+% Amy Hendrickson, 8/18/94, 3/6/96
+%
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble.  Width
+% can be specified either with sample text given in a template line,
+% or in percent of \hsize, the current width of text on page.
+
+% Table can continue over pages but will only break between lines.
+
+% To make preamble:
+%
+% Either define widths of columns in terms of percent of \hsize:
+%   @multitable @columnfractions .25 .3 .45
+%   @item ...
+%
+%   Numbers following @columnfractions are the percent of the total
+%   current hsize to be used for each column. You may use as many
+%   columns as desired.
+
+
+% Or use a template:
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item ...
+%   using the widest term desired in each column.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+%     @multitable {Column 1 template} {Column 2 template} {Column 3
+%      template}
+% Not:
+%     @multitable {Column 1 template} {Column 2 template}
+%      {Column 3 template}
+
+% Each new table line starts with @item, each subsequent new column
+% starts with @tab. Empty columns may be produced by supplying @tab's
+% with nothing between them for as many times as empty columns are needed,
+% ie, @tab@tab@tab will produce two empty columns.
+
+% @item, @tab, @multitable or @end multitable do not need to be on their
+% own lines, but it will not hurt if they are.
+
+% Sample multitable:
+
+%   @multitable {Column 1 template} {Column 2 template} {Column 3 template}
+%   @item first col stuff @tab second col stuff @tab third col
+%   @item
+%   first col stuff
+%   @tab
+%   second col stuff
+%   @tab
+%   third col
+%   @item first col stuff @tab second col stuff
+%   @tab Many paragraphs of text may be used in any column.
+%
+%         They will wrap at the width determined by the template.
+%   @item@tab@tab This will be in third column.
+%   @end multitable
+
+% Default dimensions may be reset by user.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+%                                                            to baseline.
+%   0pt means it depends on current normal line spacing.
+%
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
+
+% Macros used to set up halign preamble:
+%
+\let\endsetuptable\relax
+\def\xendsetuptable{\endsetuptable}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
+\newif\ifsetpercent
+
+% #1 is the part of the @columnfraction before the decimal point, which
+% is presumably either 0 or the empty string (but we don't check, we
+% just throw it away).  #2 is the decimal part, which we use as the
+% percent of \hsize for this column.
+\def\pickupwholefraction#1.#2 {%
+  \global\advance\colcount by 1
+  \expandafter\xdef\csname col\the\colcount\endcsname{.#2\hsize}%
+  \setuptable
+}
+
+\newcount\colcount
+\def\setuptable#1{%
+  \def\firstarg{#1}%
+  \ifx\firstarg\xendsetuptable
+    \let\go = \relax
+  \else
+    \ifx\firstarg\xcolumnfractions
+      \global\setpercenttrue
+    \else
+      \ifsetpercent
+         \let\go\pickupwholefraction
+      \else
+         \global\advance\colcount by 1
+         \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a
+                   % separator; typically that is always in the input, anyway.
+         \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
+      \fi
+    \fi
+    \ifx\go\pickupwholefraction
+      % Put the argument back for the \pickupwholefraction call, so
+      % we'll always have a period there to be parsed.
+      \def\go{\pickupwholefraction#1}%
+    \else
+      \let\go = \setuptable
+    \fi%
+  \fi
+  \go
+}
+
+% @multitable ... @end multitable definitions:
+%
+\def\multitable{\parsearg\dotable}
+\def\dotable#1{\bgroup
+  \vskip\parskip
+  \let\item=\crcrwithfootnotes
+  % A \tab used to include \hskip1sp.  But then the space in a template
+  % line is not enough.  That is bad.  So let's go back to just & until
+  % we encounter the problem it was intended to solve again.  --karl,
+  % nathan@acm.org, 20apr99.
+  \let\tab=&%
+  \let\startfootins=\startsavedfootnote
+  \tolerance=9500
+  \hbadness=9500
+  \setmultitablespacing
+  \parskip=\multitableparskip
+  \parindent=\multitableparindent
+  \overfullrule=0pt
+  \global\colcount=0
+  \def\Emultitable{%
+    \global\setpercentfalse
+    \crcrwithfootnotes\crcr
+    \egroup\egroup
+  }%
+  %
+  % To parse everything between @multitable and @item:
+  \setuptable#1 \endsetuptable
+  %
+  % \everycr will reset column counter, \colcount, at the end of
+  % each line. Every column entry will cause \colcount to advance by one.
+  % The table preamble
+  % looks at the current \colcount to find the correct column width.
+  \everycr{\noalign{%
+  %
+  % \filbreak%% keeps underfull box messages off when table breaks over pages.
+  % Maybe so, but it also creates really weird page breaks when the table
+  % breaks over pages. Wouldn't \vfil be better?  Wait until the problem
+  % manifests itself, so it can be fixed for real --karl.
+    \global\colcount=0\relax}}%
+  %
+  % This preamble sets up a generic column definition, which will
+  % be used as many times as user calls for columns.
+  % \vtop will set a single line and will also let text wrap and
+  % continue for many paragraphs if desired.
+  \halign\bgroup&\global\advance\colcount by 1\relax
+    \multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
+  %
+  % In order to keep entries from bumping into each other
+  % we will add a \leftskip of \multitablecolspace to all columns after
+  % the first one.
+  %
+  % If a template has been used, we will add \multitablecolspace
+  % to the width of each template entry.
+  %
+  % If the user has set preamble in terms of percent of \hsize we will
+  % use that dimension as the width of the column, and the \leftskip
+  % will keep entries from bumping into each other.  Table will start at
+  % left margin and final column will justify at right margin.
+  %
+  % Make sure we don't inherit \rightskip from the outer environment.
+  \rightskip=0pt
+  \ifnum\colcount=1
+    % The first column will be indented with the surrounding text.
+    \advance\hsize by\leftskip
+  \else
+    \ifsetpercent \else
+      % If user has not set preamble in terms of percent of \hsize
+      % we will advance \hsize by \multitablecolspace.
+      \advance\hsize by \multitablecolspace
+    \fi
+   % In either case we will make \leftskip=\multitablecolspace:
+  \leftskip=\multitablecolspace
+  \fi
+  % Ignoring space at the beginning and end avoids an occasional spurious
+  % blank line, when TeX decides to break the line at the space before the
+  % box from the multistrut, so the strut ends up on a line by itself.
+  % For example:
+  % @multitable @columnfractions .11 .89
+  % @item @code{#}
+  % @tab Legal holiday which is valid in major parts of the whole country.
+  % Is automatically provided with highlighting sequences respectively marking
+  % characters.
+  \noindent\ignorespaces##\unskip\multistrut}\cr
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+\setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip
+\global\advance\multitablelinespace by-\ht0
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+\else
+%% FIXME: what is \box0 supposed to be?
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%%        If so, set to same dimension as multitablelinespace.
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+                                      %% than skip between lines in the table.
+\fi}
+
+% In case a @footnote appears inside an alignment, save the footnote
+% text to a box and make the \insert when a row of the table is
+% finished.  Otherwise, the insertion is lost, it never migrates to the
+% main vertical list.  --kasal, 22jan03.
+%
+\newbox\savedfootnotes
+%
+% \dotable \let's \startfootins to this, so that \dofootnote will call
+% it instead of starting the insertion right away.
+\def\startsavedfootnote{%
+  \global\setbox\savedfootnotes = \vbox\bgroup
+    \unvbox\savedfootnotes
+}
+\def\crcrwithfootnotes{%
+  \crcr
+  \ifvoid\savedfootnotes \else
+    \noalign{\insert\footins{\box\savedfootnotes}}%
+  \fi
+}
+
+\message{conditionals,}
+% Prevent errors for section commands.
+% Used in @ignore and in failing conditionals.
+\def\ignoresections{%
+  \let\appendix=\relax
+  \let\appendixsec=\relax
+  \let\appendixsection=\relax
+  \let\appendixsubsec=\relax
+  \let\appendixsubsection=\relax
+  \let\appendixsubsubsec=\relax
+  \let\appendixsubsubsection=\relax
+  %\let\begin=\relax
+  %\let\bye=\relax
+  \let\centerchap=\relax
+  \let\chapter=\relax
+  \let\contents=\relax
+  \let\section=\relax
+  \let\smallbook=\relax
+  \let\subsec=\relax
+  \let\subsection=\relax
+  \let\subsubsec=\relax
+  \let\subsubsection=\relax
+  \let\titlepage=\relax
+  \let\top=\relax
+  \let\unnumbered=\relax
+  \let\unnumberedsec=\relax
+  \let\unnumberedsection=\relax
+  \let\unnumberedsubsec=\relax
+  \let\unnumberedsubsection=\relax
+  \let\unnumberedsubsubsec=\relax
+  \let\unnumberedsubsubsection=\relax
+}
+
+% Ignore @ignore, @ifhtml, @ifinfo, and the like.
+%
+\def\direntry{\doignore{direntry}}
+\def\documentdescriptionword{documentdescription}
+\def\documentdescription{\doignore{documentdescription}}
+\def\html{\doignore{html}}
+\def\ifhtml{\doignore{ifhtml}}
+\def\ifinfo{\doignore{ifinfo}}
+\def\ifnottex{\doignore{ifnottex}}
+\def\ifplaintext{\doignore{ifplaintext}}
+\def\ifxml{\doignore{ifxml}}
+\def\ignore{\doignore{ignore}}
+\def\menu{\doignore{menu}}
+\def\xml{\doignore{xml}}
+
+% @dircategory CATEGORY  -- specify a category of the dir file
+% which this file should belong to.  Ignore this in TeX.
+\let\dircategory = \comment
+
+% Ignore text until a line `@end #1', keeping track of nested conditionals.
+%
+% A count to remember the depth of nesting.
+\newcount\doignorecount
+
+\def\doignore#1{\begingroup
+  % Don't complain about control sequences we have declared \outer.
+  \ignoresections
+  %
+  % Make sure that spaces turn into tokens that match what \doignoretext wants.
+  \catcode\spaceChar = 10
+  %
+  % Ignore braces, so mismatched braces don't cause trouble.
+  \catcode`\{ = 9
+  \catcode`\} = 9
+  %
+  % Count number of #1's that we've seen.
+  \doignorecount = 0
+  %
+  % Swallow text until we reach the matching `@end #1'.
+  \expandafter \dodoignore \csname#1\endcsname {#1}%
+}
+
+{ \catcode`@=11 % We want to use \ST@P which cannot appear in texinfo source.
+  \obeylines %
+  %
+  \gdef\dodoignore#1#2{%
+    % #1 contains, e.g., \ifinfo, a.k.a. @ifinfo.
+    % #2 contains the string `ifinfo'.
+    %
+    % Define a command to find the next `@end #2', which must be on a line
+    % by itself.
+    \long\def\doignoretext##1^^M\end #2{\doignoretextyyy##1^^M#1\ST@P}%
+    % And this command to find another #1 command, at the beginning of a
+    % line.  (Otherwise, we would consider a line `@c @ifset', for
+    % example, to count as an @ifset for nesting.)
+    \long\def\doignoretextyyy##1^^M#1##2\ST@P{\doignoreyyy{##2}\ST@P}%
+    %
+    % And now expand that command.
+    \obeylines %
+    \doignoretext ^^M%
+  }%
+}
+
+\def\doignoreyyy#1{%
+  \def\temp{#1}%
+  \ifx\temp\empty                      % Nothing found.
+    \let\next\doignoretextzzz
+  \else                                        % Found a nested condition, ...
+    \advance\doignorecount by 1
+    \let\next\doignoretextyyy          % ..., look for another.
+    % If we're here, #1 ends with ^^M\ifinfo (for example).
+  \fi
+  \next #1% the token \ST@P is present just after this macro.
+}
+
+% We have to swallow the remaining "\ST@P".
+% 
+\def\doignoretextzzz#1{%
+  \ifnum\doignorecount = 0     % We have just found the outermost @end.
+    \let\next\enddoignore
+  \else                                % Still inside a nested condition.
+    \advance\doignorecount by -1
+    \let\next\doignoretext      % Look for the next @end.
+  \fi
+  \next
+}
+
+% Finish off ignored text.
+\def\enddoignore{\endgroup\ignorespaces}
+
+
+% @set VAR sets the variable VAR to an empty value.
+% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
+%
+% Since we want to separate VAR from REST-OF-LINE (which might be
+% empty), we can't just use \parsearg; we have to insert a space of our
+% own to delimit the rest of the line, and then take it out again if we
+% didn't need it.  Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
+%
+\def\set{\begingroup\catcode` =10
+  \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
+  \parsearg\setxxx}
+\def\setxxx#1{\setyyy#1 \endsetyyy}
+\def\setyyy#1 #2\endsetyyy{%
+  \def\temp{#2}%
+  \ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
+  \else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
+  \fi
+  \endgroup
+}
+% Can't use \xdef to pre-expand #2 and save some time, since \temp or
+% \next or other control sequences that we've defined might get us into
+% an infinite loop. Consider `@set foo @cite{bar}'.
+\def\setzzz#1#2 \endsetzzz{\expandafter\gdef\csname SET#1\endcsname{#2}}
+
+% @clear VAR clears (i.e., unsets) the variable VAR.
+%
+\def\clear{\parsearg\clearxxx}
+\def\clearxxx#1{\global\expandafter\let\csname SET#1\endcsname=\relax}
+
+% @value{foo} gets the text saved in variable foo.
+{
+  \catcode`\_ = \active
+  %
+  % We might end up with active _ or - characters in the argument if
+  % we're called from @code, as @code{@value{foo-bar_}}.  So \let any
+  % such active characters to their normal equivalents.
+  \gdef\value{\begingroup
+    \catcode`\-=\other \catcode`\_=\other
+    \indexbreaks \let_\normalunderscore
+    \valuexxx}
+}
+\def\valuexxx#1{\expandablevalue{#1}\endgroup}
+
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we \let\value to this in \indexdummies).  Ones
+% whose names contain - or _ still won't work, but we can't do anything
+% about that.  The command has to be fully expandable (if the variable
+% is set), since the result winds up in the index file.  This means that
+% if the variable's value contains other Texinfo commands, it's almost
+% certain it will fail (although perhaps we could fix that with
+% sufficient work to do a one-level expansion on the result, instead of
+% complete).
+%
+\def\expandablevalue#1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    {[No value for ``#1'']}%
+    \message{Variable `#1', used in @value, is not set.}%
+  \else
+    \csname SET#1\endcsname
+  \fi
+}
+
+% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
+% with @set.
+%
+\def\ifset{\parsearg\doifset}
+\def\doifset#1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \let\next=\ifsetfail
+  \else
+    \let\next=\ifsetsucceed
+  \fi
+  \next
+}
+\def\ifsetsucceed{\conditionalsucceed{ifset}}
+\def\ifsetfail{\doignore{ifset}}
+\defineunmatchedend{ifset}
+
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
+% defined with @set, or has been undefined with @clear.
+%
+\def\ifclear{\parsearg\doifclear}
+\def\doifclear#1{%
+  \expandafter\ifx\csname SET#1\endcsname\relax
+    \let\next=\ifclearsucceed
+  \else
+    \let\next=\ifclearfail
+  \fi
+  \next
+}
+\def\ifclearsucceed{\conditionalsucceed{ifclear}}
+\def\ifclearfail{\doignore{ifclear}}
+\defineunmatchedend{ifclear}
+
+% @iftex, @ifnothtml, @ifnotinfo, @ifnotplaintext always succeed; we
+% read the text following, through the first @end iftex (etc.).  Make
+% `@end iftex' (etc.) valid only after an @iftex.
+%
+\def\iftex{\conditionalsucceed{iftex}}
+\def\ifnothtml{\conditionalsucceed{ifnothtml}}
+\def\ifnotinfo{\conditionalsucceed{ifnotinfo}}
+\def\ifnotplaintext{\conditionalsucceed{ifnotplaintext}}
+\defineunmatchedend{iftex}
+\defineunmatchedend{ifnothtml}
+\defineunmatchedend{ifnotinfo}
+\defineunmatchedend{ifnotplaintext}
+
+% True conditional.  Since \set globally defines its variables, we can
+% just start and end a group (to keep the @end definition undefined at
+% the outer level).
+%
+\def\conditionalsucceed#1{\begingroup
+  \expandafter\def\csname E#1\endcsname{\endgroup}%
+}
+
+% @defininfoenclose.
+\let\definfoenclose=\comment
+
+
+\message{indexing,}
+% Index generation facilities
+
+% Define \newwrite to be identical to plain tex's \newwrite
+% except not \outer, so it can be used within \newindex.
+{\catcode`\@=11
+\gdef\newwrite{\alloc@7\write\chardef\sixt@@n}}
+
+% \newindex {foo} defines an index named foo.
+% It automatically defines \fooindex such that
+% \fooindex ...rest of line... puts an entry in the index foo.
+% It also defines \fooindfile to be the number of the output channel for
+% the file that accumulates this index.  The file's extension is foo.
+% The name of an index should be no more than 2 characters long
+% for the sake of vms.
+%
+\def\newindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%     % Define @#1index
+    \noexpand\doindex{#1}}
+}
+
+% @defindex foo  ==  \newindex{foo}
+%
+\def\defindex{\parsearg\newindex}
+
+% Define @defcodeindex, like @defindex except put all entries in @code.
+%
+\def\defcodeindex{\parsearg\newcodeindex}
+%
+\def\newcodeindex#1{%
+  \iflinks
+    \expandafter\newwrite \csname#1indfile\endcsname
+    \openout \csname#1indfile\endcsname \jobname.#1
+  \fi
+  \expandafter\xdef\csname#1index\endcsname{%
+    \noexpand\docodeindex{#1}}%
+}
+
+
+% @synindex foo bar    makes index foo feed into index bar.
+% Do this instead of @defindex foo if you don't want it as a separate index.
+%
+% @syncodeindex foo bar   similar, but put all entries made for index foo
+% inside @code.
+%
+\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}}
+\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}}
+
+% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo),
+% #3 the target index (bar).
+\def\dosynindex#1#2#3{%
+  % Only do \closeout if we haven't already done it, else we'll end up
+  % closing the target index.
+  \expandafter \ifx\csname donesynindex#2\endcsname \undefined
+    % The \closeout helps reduce unnecessary open files; the limit on the
+    % Acorn RISC OS is a mere 16 files.
+    \expandafter\closeout\csname#2indfile\endcsname
+    \expandafter\let\csname\donesynindex#2\endcsname = 1
+  \fi
+  % redefine \fooindfile:
+  \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
+  \expandafter\let\csname#2indfile\endcsname=\temp
+  % redefine \fooindex:
+  \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}%
+}
+
+% Define \doindex, the driver for all \fooindex macros.
+% Argument #1 is generated by the calling \fooindex macro,
+%  and it is "foo", the name of the index.
+
+% \doindex just uses \parsearg; it calls \doind for the actual work.
+% This is because \doind is more useful to call from other macros.
+
+% There is also \dosubind {index}{topic}{subtopic}
+% which makes an entry in a two-level index such as the operation index.
+
+\def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer}
+\def\singleindexer #1{\doind{\indexname}{#1}}
+
+% like the previous two, but they put @code around the argument.
+\def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer}
+\def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}}
+
+% Take care of Texinfo commands that can appear in an index entry.
+% Since there are some commands we want to expand, and others we don't,
+% we have to laboriously prevent expansion for those that we don't.
+%
+\def\indexdummies{%
+  \def\@{@}% change to @@ when we switch to @ as escape char in index files.
+  \def\ {\realbackslash\space }%
+  % Need these in case \tex is in effect and \{ is a \delimiter again.
+  % But can't use \lbracecmd and \rbracecmd because texindex assumes
+  % braces and backslashes are used only as delimiters.
+  \let\{ = \mylbrace
+  \let\} = \myrbrace
+  %
+  % \definedummyword defines \#1 as \realbackslash #1\space, thus
+  % effectively preventing its expansion.  This is used only for control
+  % words, not control letters, because the \space would be incorrect
+  % for control characters, but is needed to separate the control word
+  % from whatever follows.
+  %
+  % For control letters, we have \definedummyletter, which omits the
+  % space.
+  %
+  % These can be used both for control words that take an argument and
+  % those that do not.  If it is followed by {arg} in the input, then
+  % that will dutifully get written to the index (or wherever).
+  %
+  \def\definedummyword##1{%
+    \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}%
+  }%
+  \def\definedummyletter##1{%
+    \expandafter\def\csname ##1\endcsname{\realbackslash ##1}%
+  }%
+  %
+  % Do the redefinitions.
+  \commondummies
+}
+
+% For the aux file, @ is the escape character.  So we want to redefine
+% everything using @ instead of \realbackslash.  When everything uses
+% @, this will be simpler.
+%
+\def\atdummies{%
+  \def\@{@@}%
+  \def\ {@ }%
+  \let\{ = \lbraceatcmd
+  \let\} = \rbraceatcmd
+  %
+  % (See comments in \indexdummies.)
+  \def\definedummyword##1{%
+    \expandafter\def\csname ##1\endcsname{@##1\space}%
+  }%
+  \def\definedummyletter##1{%
+    \expandafter\def\csname ##1\endcsname{@##1}%
+  }%
+  %
+  % Do the redefinitions.
+  \commondummies
+}
+
+% Called from \indexdummies and \atdummies.  \definedummyword and
+% \definedummyletter must be defined first.
+%
+\def\commondummies{%
+  %
+  \normalturnoffactive
+  %
+  % Control letters and accents.
+  \definedummyletter{_}%
+  \definedummyletter{,}%
+  \definedummyletter{"}%
+  \definedummyletter{`}%
+  \definedummyletter{'}%
+  \definedummyletter{^}%
+  \definedummyletter{~}%
+  \definedummyletter{=}%
+  \definedummyword{u}%
+  \definedummyword{v}%
+  \definedummyword{H}%
+  \definedummyword{dotaccent}%
+  \definedummyword{ringaccent}%
+  \definedummyword{tieaccent}%
+  \definedummyword{ubaraccent}%
+  \definedummyword{udotaccent}%
+  \definedummyword{dotless}%
+  %
+  % Other non-English letters.
+  \definedummyword{AA}%
+  \definedummyword{AE}%
+  \definedummyword{L}%
+  \definedummyword{OE}%
+  \definedummyword{O}%
+  \definedummyword{aa}%
+  \definedummyword{ae}%
+  \definedummyword{l}%
+  \definedummyword{oe}%
+  \definedummyword{o}%
+  \definedummyword{ss}%
+  %
+  % Although these internal commands shouldn't show up, sometimes they do.
+  \definedummyword{bf}%
+  \definedummyword{gtr}%
+  \definedummyword{hat}%
+  \definedummyword{less}%
+  \definedummyword{sf}%
+  \definedummyword{sl}%
+  \definedummyword{tclose}%
+  \definedummyword{tt}%
+  %
+  % Texinfo font commands.
+  \definedummyword{b}%
+  \definedummyword{i}%
+  \definedummyword{r}%
+  \definedummyword{sc}%
+  \definedummyword{t}%
+  %
+  \definedummyword{TeX}%
+  \definedummyword{acronym}%
+  \definedummyword{cite}%
+  \definedummyword{code}%
+  \definedummyword{command}%
+  \definedummyword{dfn}%
+  \definedummyword{dots}%
+  \definedummyword{emph}%
+  \definedummyword{env}%
+  \definedummyword{file}%
+  \definedummyword{kbd}%
+  \definedummyword{key}%
+  \definedummyword{math}%
+  \definedummyword{option}%
+  \definedummyword{samp}%
+  \definedummyword{strong}%
+  \definedummyword{uref}%
+  \definedummyword{url}%
+  \definedummyword{var}%
+  \definedummyword{verb}%
+  \definedummyword{w}%
+  %
+  % Assorted special characters.
+  \definedummyword{bullet}%
+  \definedummyword{copyright}%
+  \definedummyword{dots}%
+  \definedummyword{enddots}%
+  \definedummyword{equiv}%
+  \definedummyword{error}%
+  \definedummyword{expansion}%
+  \definedummyword{minus}%
+  \definedummyword{pounds}%
+  \definedummyword{point}%
+  \definedummyword{print}%
+  \definedummyword{result}%
+  %
+  % Handle some cases of @value -- where the variable name does not
+  % contain - or _, and the value does not contain any
+  % (non-fully-expandable) commands.
+  \let\value = \expandablevalue
+  %
+  % Normal spaces, not active ones.
+  \unsepspaces
+  %
+  % No macro expansion.
+  \turnoffmacros
+}
+
+% If an index command is used in an @example environment, any spaces
+% therein should become regular spaces in the raw index file, not the
+% expansion of \tie (\leavevmode \penalty \@M \ ).
+{\obeyspaces
+ \gdef\unsepspaces{\obeyspaces\let =\space}}
+
+
+% \indexnofonts is used when outputting the strings to sort the index
+% by, and when constructing control sequence names.  It eliminates all
+% control sequences and just writes whatever the best ASCII sort string
+% would be for a given command (usually its argument).
+%
+\def\indexdummytex{TeX}
+\def\indexdummydots{...}
+%
+\def\indexnofonts{%
+  \def\ { }%
+  \def\@{@}%
+  % how to handle braces?
+  \def\_{\normalunderscore}%
+  %
+  \let\,=\asis
+  \let\"=\asis
+  \let\`=\asis
+  \let\'=\asis
+  \let\^=\asis
+  \let\~=\asis
+  \let\==\asis
+  \let\u=\asis
+  \let\v=\asis
+  \let\H=\asis
+  \let\dotaccent=\asis
+  \let\ringaccent=\asis
+  \let\tieaccent=\asis
+  \let\ubaraccent=\asis
+  \let\udotaccent=\asis
+  \let\dotless=\asis
+  %
+  % Other non-English letters.
+  \def\AA{AA}%
+  \def\AE{AE}%
+  \def\L{L}%
+  \def\OE{OE}%
+  \def\O{O}%
+  \def\aa{aa}%
+  \def\ae{ae}%
+  \def\l{l}%
+  \def\oe{oe}%
+  \def\o{o}%
+  \def\ss{ss}%
+  \def\exclamdown{!}%
+  \def\questiondown{?}%
+  %
+  % Don't no-op \tt, since it isn't a user-level command
+  % and is used in the definitions of the active chars like <, >, |, etc.
+  % Likewise with the other plain tex font commands.
+  %\let\tt=\asis
+  %
+  % Texinfo font commands.
+  \let\b=\asis
+  \let\i=\asis
+  \let\r=\asis
+  \let\sc=\asis
+  \let\t=\asis
+  %
+  \let\TeX=\indexdummytex
+  \let\acronym=\asis
+  \let\cite=\asis
+  \let\code=\asis
+  \let\command=\asis
+  \let\dfn=\asis
+  \let\dots=\indexdummydots
+  \let\emph=\asis
+  \let\env=\asis
+  \let\file=\asis
+  \let\kbd=\asis
+  \let\key=\asis
+  \let\math=\asis
+  \let\option=\asis
+  \let\samp=\asis
+  \let\strong=\asis
+  \let\uref=\asis
+  \let\url=\asis
+  \let\var=\asis
+  \let\verb=\asis
+  \let\w=\asis
+}
+
+\let\indexbackslash=0  %overridden during \printindex.
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
+% Most index entries go through here, but \dosubind is the general case.
+%
+\def\doind#1#2{\dosubind{#1}{#2}{}}
+
+% Workhorse for all \fooindexes.
+% #1 is name of index, #2 is stuff to put there, #3 is subentry --
+% \empty if called from \doind, as we usually are.  The main exception
+% is with defuns, which call us directly.
+%
+\def\dosubind#1#2#3{%
+  \iflinks
+  {%
+    % Store the main index entry text (including the third arg).
+    \toks0 = {#2}%
+    % If third arg is present, precede it with space.
+    \def\thirdarg{#3}%
+    \ifx\thirdarg\empty \else
+      \toks0 = \expandafter{\the\toks0 \space #3}%
+    \fi
+    %
+    \edef\writeto{\csname#1indfile\endcsname}%
+    %
+    \ifvmode
+      \dosubindsanitize
+    \else
+      \dosubindwrite
+    \fi
+  }%
+  \fi
+}
+
+% Write the entry to the index file:
+%
+\def\dosubindwrite{%
+  % Put the index entry in the margin if desired.
+  \ifx\SETmarginindex\relax\else
+    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
+  \fi
+  %
+  % Remember, we are within a group.
+  \indexdummies % Must do this here, since \bf, etc expand at this stage
+  \escapechar=`\\
+  \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+      % so it will be output as is; and it will print as backslash.
+  %
+  % Process the index entry with all font commands turned off, to
+  % get the string to sort by.
+  {\indexnofonts
+   \edef\temp{\the\toks0}% need full expansion
+   \xdef\indexsorttmp{\temp}%
+  }%
+  %
+  % Set up the complete index entry, with both the sort key and
+  % the original text, including any font commands.  We write
+  % three arguments to \entry to the .?? file (four in the
+  % subentry case), texindex reduces to two when writing the .??s
+  % sorted result.
+  \edef\temp{%
+    \write\writeto{%
+      \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}%
+  }%
+  \temp
+}
+
+% Take care of unwanted page breaks:
+%
+% If a skip is the last thing on the list now, preserve it
+% by backing up by \lastskip, doing the \write, then inserting
+% the skip again.  Otherwise, the whatsit generated by the
+% \write will make \lastskip zero.  The result is that sequences
+% like this:
+% @end defun
+% @tindex whatever
+% @defun ...
+% will have extra space inserted, because the \medbreak in the
+% start of the @defun won't see the skip inserted by the @end of
+% the previous defun.
+%
+% But don't do any of this if we're not in vertical mode.  We
+% don't want to do a \vskip and prematurely end a paragraph.
+%
+% Avoid page breaks due to these extra skips, too.
+%
+\def\dosubindsanitize{%
+  % \lastskip and \lastpenalty cannot both be nonzero simultaneously.
+  \skip0 = \lastskip
+  \count255 = \lastpenalty
+  %
+  % If \lastskip is nonzero, that means the last item was a
+  % skip.  And since a skip is discardable, that means this
+  % -\skip0 glue we're inserting is preceded by a
+  % non-discardable item, therefore it is not a potential
+  % breakpoint, therefore no \nobreak needed.
+  \ifdim\lastskip = 0pt \else \vskip-\skip0 \fi
+  %
+  \dosubindwrite
+  %
+  \ifdim\skip0 = 0pt
+    % if \lastskip was zero, perhaps the last item was a
+    % penalty, and perhaps it was >=10000, e.g., a \nobreak.
+    % In that case, we want to re-insert the penalty; since we
+    % just inserted a non-discardable item, any following glue
+    % (such as a \parskip) would be a breakpoint.  For example:
+    %   @deffn deffn-whatever
+    %   @vindex index-whatever
+    %   Description.
+    % would allow a break between the index-whatever whatsit
+    % and the "Description." paragraph.
+    \ifnum\count255>9999 \nobreak \fi
+  \else
+    % On the other hand, if we had a nonzero \lastskip,
+    % this make-up glue would be preceded by a non-discardable item
+    % (the whatsit from the \write), so we must insert a \nobreak.
+    \nobreak\vskip\skip0
+  \fi
+}
+
+% The index entry written in the file actually looks like
+%  \entry {sortstring}{page}{topic}
+% or
+%  \entry {sortstring}{page}{topic}{subtopic}
+% The texindex program reads in these files and writes files
+% containing these kinds of lines:
+%  \initial {c}
+%     before the first topic whose initial is c
+%  \entry {topic}{pagelist}
+%     for a topic that is used without subtopics
+%  \primary {topic}
+%     for the beginning of a topic that is used with subtopics
+%  \secondary {subtopic}{pagelist}
+%     for each subtopic.
+
+% Define the user-accessible indexing commands
+% @findex, @vindex, @kindex, @cindex.
+
+\def\findex {\fnindex}
+\def\kindex {\kyindex}
+\def\cindex {\cpindex}
+\def\vindex {\vrindex}
+\def\tindex {\tpindex}
+\def\pindex {\pgindex}
+
+\def\cindexsub {\begingroup\obeylines\cindexsub}
+{\obeylines %
+\gdef\cindexsub "#1" #2^^M{\endgroup %
+\dosubind{cp}{#2}{#1}}}
+
+% Define the macros used in formatting output of the sorted index material.
+
+% @printindex causes a particular index (the ??s file) to get printed.
+% It does not print any chapter heading (usually an @unnumbered).
+%
+\def\printindex{\parsearg\doprintindex}
+\def\doprintindex#1{\begingroup
+  \dobreak \chapheadingskip{10000}%
+  %
+  \smallfonts \rm
+  \tolerance = 9500
+  \everypar = {}% don't want the \kern\-parindent from indentation suppression.
+  \indexbreaks
+  %
+  % See if the index file exists and is nonempty.
+  % Change catcode of @ here so that if the index file contains
+  % \initial {@}
+  % as its first line, TeX doesn't complain about mismatched braces
+  % (because it thinks @} is a control sequence).
+  \catcode`\@ = 11
+  \openin 1 \jobname.#1s
+  \ifeof 1
+    % \enddoublecolumns gets confused if there is no text in the index,
+    % and it loses the chapter title and the aux file entries for the
+    % index.  The easiest way to prevent this problem is to make sure
+    % there is some text.
+    \putwordIndexNonexistent
+  \else
+    %
+    % If the index file exists but is empty, then \openin leaves \ifeof
+    % false.  We have to make TeX try to read something from the file, so
+    % it can discover if there is anything in it.
+    \read 1 to \temp
+    \ifeof 1
+      \putwordIndexIsEmpty
+    \else
+      % Index files are almost Texinfo source, but we use \ as the escape
+      % character.  It would be better to use @, but that's too big a change
+      % to make right now.
+      \def\indexbackslash{\rawbackslashxx}%
+      \catcode`\\ = 0
+      \escapechar = `\\
+      \begindoublecolumns
+      \input \jobname.#1s
+      \enddoublecolumns
+    \fi
+  \fi
+  \closein 1
+\endgroup}
+
+% These macros are used by the sorted index file itself.
+% Change them to control the appearance of the index.
+
+\def\initial#1{{%
+  % Some minor font changes for the special characters.
+  \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt
+  %
+  % Remove any glue we may have, we'll be inserting our own.
+  \removelastskip
+  %
+  % We like breaks before the index initials, so insert a bonus.
+  \penalty -300
+  %
+  % Typeset the initial.  Making this add up to a whole number of
+  % baselineskips increases the chance of the dots lining up from column
+  % to column.  It still won't often be perfect, because of the stretch
+  % we need before each entry, but it's better.
+  %
+  % No shrink because it confuses \balancecolumns.
+  \vskip 1.67\baselineskip plus .5\baselineskip
+  \leftline{\secbf #1}%
+  \vskip .33\baselineskip plus .1\baselineskip
+  %
+  % Do our best not to break after the initial.
+  \nobreak
+}}
+
+% This typesets a paragraph consisting of #1, dot leaders, and then #2
+% flush to the right margin.  It is used for index and table of contents
+% entries.  The paragraph is indented by \leftskip.
+%
+\def\entry#1#2{\begingroup
+  %
+  % Start a new paragraph if necessary, so our assignments below can't
+  % affect previous text.
+  \par
+  %
+  % Do not fill out the last line with white space.
+  \parfillskip = 0in
+  %
+  % No extra space above this paragraph.
+  \parskip = 0in
+  %
+  % Do not prefer a separate line ending with a hyphen to fewer lines.
+  \finalhyphendemerits = 0
+  %
+  % \hangindent is only relevant when the entry text and page number
+  % don't both fit on one line.  In that case, bob suggests starting the
+  % dots pretty far over on the line.  Unfortunately, a large
+  % indentation looks wrong when the entry text itself is broken across
+  % lines.  So we use a small indentation and put up with long leaders.
+  %
+  % \hangafter is reset to 1 (which is the value we want) at the start
+  % of each paragraph, so we need not do anything with that.
+  \hangindent = 2em
+  %
+  % When the entry text needs to be broken, just fill out the first line
+  % with blank space.
+  \rightskip = 0pt plus1fil
+  %
+  % A bit of stretch before each entry for the benefit of balancing columns.
+  \vskip 0pt plus1pt
+  %
+  % Start a ``paragraph'' for the index entry so the line breaking
+  % parameters we've set above will have an effect.
+  \noindent
+  %
+  % Insert the text of the index entry.  TeX will do line-breaking on it.
+  #1%
+  % The following is kludged to not output a line of dots in the index if
+  % there are no page numbers.  The next person who breaks this will be
+  % cursed by a Unix daemon.
+  \def\tempa{{\rm }}%
+  \def\tempb{#2}%
+  \edef\tempc{\tempa}%
+  \edef\tempd{\tempb}%
+  \ifx\tempc\tempd\ \else%
+    %
+    % If we must, put the page number on a line of its own, and fill out
+    % this line with blank space.  (The \hfil is overwhelmed with the
+    % fill leaders glue in \indexdotfill if the page number does fit.)
+    \hfil\penalty50
+    \null\nobreak\indexdotfill % Have leaders before the page number.
+    %
+    % The `\ ' here is removed by the implicit \unskip that TeX does as
+    % part of (the primitive) \par.  Without it, a spurious underfull
+    % \hbox ensues.
+    \ifpdf
+      \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+    \else
+      \ #2% The page number ends the paragraph.
+    \fi
+  \fi%
+  \par
+\endgroup}
+
+% Like \dotfill except takes at least 1 em.
+\def\indexdotfill{\cleaders
+  \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill}
+
+\def\primary #1{\line{#1\hfil}}
+
+\newskip\secondaryindent \secondaryindent=0.5cm
+\def\secondary#1#2{{%
+  \parfillskip=0in
+  \parskip=0in
+  \hangindent=1in
+  \hangafter=1
+  \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill
+  \ifpdf
+    \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+  \else
+    #2
+  \fi
+  \par
+}}
+
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
+
+\newbox\partialpage
+\newdimen\doublecolumnhsize
+
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
+  % Grab any single-column material above us.
+  \output = {%
+    %
+    % Here is a possibility not foreseen in manmac: if we accumulate a
+    % whole lot of material, we might end up calling this \output
+    % routine twice in a row (see the doublecol-lose test, which is
+    % essentially a couple of indexes with @setchapternewpage off).  In
+    % that case we just ship out what is in \partialpage with the normal
+    % output routine.  Generally, \partialpage will be empty when this
+    % runs and this will be a no-op.  See the indexspread.tex test case.
+    \ifvoid\partialpage \else
+      \onepageout{\pagecontents\partialpage}%
+    \fi
+    %
+    \global\setbox\partialpage = \vbox{%
+      % Unvbox the main output page.
+      \unvbox\PAGE
+      \kern-\topskip \kern\baselineskip
+    }%
+  }%
+  \eject % run that output routine to set \partialpage
+  %
+  % Use the double-column output routine for subsequent pages.
+  \output = {\doublecolumnout}%
+  %
+  % Change the page size parameters.  We could do this once outside this
+  % routine, in each of @smallbook, @afourpaper, and the default 8.5x11
+  % format, but then we repeat the same computation.  Repeating a couple
+  % of assignments once per index is clearly meaningless for the
+  % execution time, so we may as well do it in one place.
+  %
+  % First we halve the line length, less a little for the gutter between
+  % the columns.  We compute the gutter based on the line length, so it
+  % changes automatically with the paper format.  The magic constant
+  % below is chosen so that the gutter has the same value (well, +-<1pt)
+  % as it did when we hard-coded it.
+  %
+  % We put the result in a separate register, \doublecolumhsize, so we
+  % can restore it in \pagesofar, after \hsize itself has (potentially)
+  % been clobbered.
+  %
+  \doublecolumnhsize = \hsize
+    \advance\doublecolumnhsize by -.04154\hsize
+    \divide\doublecolumnhsize by 2
+  \hsize = \doublecolumnhsize
+  %
+  % Double the \vsize as well.  (We don't need a separate register here,
+  % since nobody clobbers \vsize.)
+  \vsize = 2\vsize
+}
+
+% The double-column output routine for all double-column pages except
+% the last.
+%
+\def\doublecolumnout{%
+  \splittopskip=\topskip \splitmaxdepth=\maxdepth
+  % Get the available space for the double columns -- the normal
+  % (undoubled) page height minus any material left over from the
+  % previous page.
+  \dimen@ = \vsize
+  \divide\dimen@ by 2
+  \advance\dimen@ by -\ht\partialpage
+  %
+  % box0 will be the left-hand column, box2 the right.
+  \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+  \onepageout\pagesofar
+  \unvbox255
+  \penalty\outputpenalty
+}
+%
+% Re-output the contents of the output page -- any previous material,
+% followed by the two boxes we just split, in box0 and box2.
+\def\pagesofar{%
+  \unvbox\partialpage
+  %
+  \hsize = \doublecolumnhsize
+  \wd0=\hsize \wd2=\hsize
+  \hbox to\pagewidth{\box0\hfil\box2}%
+}
+%
+% All done with double columns.
+\def\enddoublecolumns{%
+  \output = {%
+    % Split the last of the double-column material.  Leave it on the
+    % current page, no automatic page break.
+    \balancecolumns
+    %
+    % If we end up splitting too much material for the current page,
+    % though, there will be another page break right after this \output
+    % invocation ends.  Having called \balancecolumns once, we do not
+    % want to call it again.  Therefore, reset \output to its normal
+    % definition right away.  (We hope \balancecolumns will never be
+    % called on to balance too much material, but if it is, this makes
+    % the output somewhat more palatable.)
+    \global\output = {\onepageout{\pagecontents\PAGE}}%
+  }%
+  \eject
+  \endgroup % started in \begindoublecolumns
+  %
+  % \pagegoal was set to the doubled \vsize above, since we restarted
+  % the current page.  We're now back to normal single-column
+  % typesetting, so reset \pagegoal to the normal \vsize (after the
+  % \endgroup where \vsize got restored).
+  \pagegoal = \vsize
+}
+%
+% Called at the end of the double column material.
+\def\balancecolumns{%
+  \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120.
+  \dimen@ = \ht0
+  \advance\dimen@ by \topskip
+  \advance\dimen@ by-\baselineskip
+  \divide\dimen@ by 2 % target to split to
+  %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}%
+  \splittopskip = \topskip
+  % Loop until we get a decent breakpoint.
+  {%
+    \vbadness = 10000
+    \loop
+      \global\setbox3 = \copy0
+      \global\setbox1 = \vsplit3 to \dimen@
+    \ifdim\ht3>\dimen@
+      \global\advance\dimen@ by 1pt
+    \repeat
+  }%
+  %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}%
+  \setbox0=\vbox to\dimen@{\unvbox1}%
+  \setbox2=\vbox to\dimen@{\unvbox3}%
+  %
+  \pagesofar
+}
+\catcode`\@ = \other
+
+
+\message{sectioning,}
+% Chapters, sections, etc.
+
+% \unnumberedno is an oxymoron, of course.  But we count the unnumbered
+% sections so that we can refer to them unambiguously in the pdf
+% outlines by their "section number".  We avoid collisions with chapter
+% numbers by starting them at 10000.  (If a document ever has 10000
+% chapters, we're in trouble anyway, I'm sure.)
+\newcount\unnumberedno \unnumberedno = 10000
+\newcount\chapno
+\newcount\secno        \secno=0
+\newcount\subsecno     \subsecno=0
+\newcount\subsubsecno  \subsubsecno=0
+
+% This counter is funny since it counts through charcodes of letters A, B, ...
+\newcount\appendixno  \appendixno = `\@
+%
+% \def\appendixletter{\char\the\appendixno}
+% We do the following ugly conditional instead of the above simple
+% construct for the sake of pdftex, which needs the actual
+% letter in the expansion, not just typeset.
+% 
+\def\appendixletter{%
+  \ifnum\appendixno=`A A%
+  \else\ifnum\appendixno=`B B%
+  \else\ifnum\appendixno=`C C%
+  \else\ifnum\appendixno=`D D%
+  \else\ifnum\appendixno=`E E%
+  \else\ifnum\appendixno=`F F%
+  \else\ifnum\appendixno=`G G%
+  \else\ifnum\appendixno=`H H%
+  \else\ifnum\appendixno=`I I%
+  \else\ifnum\appendixno=`J J%
+  \else\ifnum\appendixno=`K K%
+  \else\ifnum\appendixno=`L L%
+  \else\ifnum\appendixno=`M M%
+  \else\ifnum\appendixno=`N N%
+  \else\ifnum\appendixno=`O O%
+  \else\ifnum\appendixno=`P P%
+  \else\ifnum\appendixno=`Q Q%
+  \else\ifnum\appendixno=`R R%
+  \else\ifnum\appendixno=`S S%
+  \else\ifnum\appendixno=`T T%
+  \else\ifnum\appendixno=`U U%
+  \else\ifnum\appendixno=`V V%
+  \else\ifnum\appendixno=`W W%
+  \else\ifnum\appendixno=`X X%
+  \else\ifnum\appendixno=`Y Y%
+  \else\ifnum\appendixno=`Z Z%
+  % The \the is necessary, despite appearances, because \appendixletter is
+  % expanded while writing the .toc file.  \char\appendixno is not
+  % expandable, thus it is written literally, thus all appendixes come out
+  % with the same letter (or @) in the toc without it.
+  \else\char\the\appendixno
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
+  \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+
+% Each @chapter defines this as the name of the chapter.
+% page headings and footings can use it.  @section does likewise.
+% However, they are not reliable, because we don't use marks.
+\def\thischapter{}
+\def\thissection{}
+
+\newcount\absseclevel % used to calculate proper heading level
+\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
+
+% @raisesections: treat @section as chapter, @subsection as section, etc.
+\def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
+
+% @lowersections: treat @chapter as section, @section as subsection, etc.
+\def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
+
+% Choose a numbered-heading macro
+% #1 is heading level if unmodified by @raisesections or @lowersections
+% #2 is text for heading
+\def\numhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+      \chapterzzz{#2}%
+  \or \seczzz{#2}%
+  \or \numberedsubseczzz{#2}%
+  \or \numberedsubsubseczzz{#2}%
+  \else
+    \ifnum \absseclevel<0 \chapterzzz{#2}%
+    \else \numberedsubsubseczzz{#2}%
+    \fi
+  \fi
+  \suppressfirstparagraphindent
+}
+
+% like \numhead, but chooses appendix heading levels
+\def\apphead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+\ifcase\absseclevel
+      \appendixzzz{#2}%
+  \or \appendixsectionzzz{#2}%
+  \or \appendixsubseczzz{#2}%
+  \or \appendixsubsubseczzz{#2}%
+  \else
+    \ifnum \absseclevel<0 \appendixzzz{#2}%
+    \else \appendixsubsubseczzz{#2}%
+    \fi
+  \fi
+  \suppressfirstparagraphindent
+}
+
+% like \numhead, but chooses numberless heading levels
+\def\unnmhead#1#2{\absseclevel=\secbase\advance\absseclevel by #1
+  \ifcase\absseclevel
+      \unnumberedzzz{#2}%
+  \or \unnumberedseczzz{#2}%
+  \or \unnumberedsubseczzz{#2}%
+  \or \unnumberedsubsubseczzz{#2}%
+  \else
+    \ifnum \absseclevel<0 \unnumberedzzz{#2}%
+    \else \unnumberedsubsubseczzz{#2}%
+    \fi
+  \fi
+  \suppressfirstparagraphindent
+}
+
+% @chapter, @appendix, @unnumbered.
+%
+\outer\def\chapter{\parsearg\chapteryyy}
+\def\chapteryyy#1{\numhead0{#1}} % normally numhead0 calls chapterzzz
+\def\chapterzzz#1{%
+  % section resetting is \global in case the chapter is in a group, such
+  % as an @include file.
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\chapno by 1
+  \message{\putwordChapter\space \the\chapno}%
+  %
+  % Write the actual heading.
+  \chapmacro{#1}{Ynumbered}{\the\chapno}%
+  %
+  % So @section and the like are numbered underneath this chapter.
+  \global\let\section = \numberedsec
+  \global\let\subsection = \numberedsubsec
+  \global\let\subsubsection = \numberedsubsubsec
+}
+
+\outer\def\appendix{\parsearg\appendixyyy}
+\def\appendixyyy#1{\apphead0{#1}} % normally apphead0 calls appendixzzz
+\def\appendixzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\appendixno by 1
+  \def\appendixnum{\putwordAppendix\space \appendixletter}%
+  \message{\appendixnum}%
+  \chapmacro{#1}{Yappendix}{\appendixletter}%
+  \global\let\section = \appendixsec
+  \global\let\subsection = \appendixsubsec
+  \global\let\subsubsection = \appendixsubsubsec
+}
+
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy#1{{\unnumberedyyy{#1}}}
+
+% @top is like @unnumbered.
+\outer\def\top{\parsearg\unnumberedyyy}
+
+\outer\def\unnumbered{\parsearg\unnumberedyyy}
+\def\unnumberedyyy#1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
+\def\unnumberedzzz#1{%
+  \global\secno=0 \global\subsecno=0 \global\subsubsecno=0
+    \global\advance\unnumberedno by 1
+  %
+  % This used to be simply \message{#1}, but TeX fully expands the
+  % argument to \message.  Therefore, if #1 contained @-commands, TeX
+  % expanded them.  For example, in `@unnumbered The @cite{Book}', TeX
+  % expanded @cite (which turns out to cause errors because \cite is meant
+  % to be executed, not expanded).
+  %
+  % Anyway, we don't want the fully-expanded definition of @cite to appear
+  % as a result of the \message, we just want `@cite' itself.  We use
+  % \the<toks register> to achieve this: TeX expands \the<toks> only once,
+  % simply yielding the contents of <toks register>.  (We also do this for
+  % the toc entries.)
+  \toks0 = {#1}\message{(\the\toks0)}%
+  %
+  \chapmacro{#1}{Ynothing}{\the\unnumberedno}%
+  %
+  \global\let\section = \unnumberedsec
+  \global\let\subsection = \unnumberedsubsec
+  \global\let\subsubsection = \unnumberedsubsubsec
+}
+
+% Sections.
+\outer\def\numberedsec{\parsearg\secyyy}
+\def\secyyy#1{\numhead1{#1}} % normally calls seczzz
+\def\seczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
+}
+
+\outer\def\appendixsection{\parsearg\appendixsecyyy}
+\outer\def\appendixsec{\parsearg\appendixsecyyy}
+\def\appendixsecyyy#1{\apphead1{#1}} % normally calls appendixsectionzzz
+\def\appendixsectionzzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
+}
+
+\outer\def\unnumberedsec{\parsearg\unnumberedsecyyy}
+\def\unnumberedsecyyy#1{\unnmhead1{#1}} % normally calls unnumberedseczzz
+\def\unnumberedseczzz#1{%
+  \global\subsecno=0 \global\subsubsecno=0  \global\advance\secno by 1
+  \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}%
+}
+
+% Subsections.
+\outer\def\numberedsubsec{\parsearg\numberedsubsecyyy}
+\def\numberedsubsecyyy#1{\numhead2{#1}} % normally calls numberedsubseczzz
+\def\numberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}%
+}
+
+\outer\def\appendixsubsec{\parsearg\appendixsubsecyyy}
+\def\appendixsubsecyyy#1{\apphead2{#1}} % normally calls appendixsubseczzz
+\def\appendixsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno}%
+}
+
+\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
+\def\unnumberedsubsecyyy#1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
+\def\unnumberedsubseczzz#1{%
+  \global\subsubsecno=0  \global\advance\subsecno by 1
+  \sectionheading{#1}{subsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno}%
+}
+
+% Subsubsections.
+\outer\def\numberedsubsubsec{\parsearg\numberedsubsubsecyyy}
+\def\numberedsubsubsecyyy#1{\numhead3{#1}} % normally numberedsubsubseczzz
+\def\numberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynumbered}%
+                 {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\def\appendixsubsubsec{\parsearg\appendixsubsubsecyyy}
+\def\appendixsubsubsecyyy#1{\apphead3{#1}} % normally appendixsubsubseczzz
+\def\appendixsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Yappendix}%
+                 {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
+\def\unnumberedsubsubsecyyy#1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
+\def\unnumberedsubsubseczzz#1{%
+  \global\advance\subsubsecno by 1
+  \sectionheading{#1}{subsubsec}{Ynothing}%
+                 {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}%
+}
+
+% These are variants which are not "outer", so they can appear in @ifinfo.
+% Actually, they are now be obsolete; ordinary section commands should work.
+\def\infotop{\parsearg\unnumberedzzz}
+\def\infounnumbered{\parsearg\unnumberedzzz}
+\def\infounnumberedsec{\parsearg\unnumberedseczzz}
+\def\infounnumberedsubsec{\parsearg\unnumberedsubseczzz}
+\def\infounnumberedsubsubsec{\parsearg\unnumberedsubsubseczzz}
+
+\def\infoappendix{\parsearg\appendixzzz}
+\def\infoappendixsec{\parsearg\appendixseczzz}
+\def\infoappendixsubsec{\parsearg\appendixsubseczzz}
+\def\infoappendixsubsubsec{\parsearg\appendixsubsubseczzz}
+
+\def\infochapter{\parsearg\chapterzzz}
+\def\infosection{\parsearg\sectionzzz}
+\def\infosubsection{\parsearg\subsectionzzz}
+\def\infosubsubsection{\parsearg\subsubsectionzzz}
+
+% These macros control what the section commands do, according
+% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
+% Define them by default for a numbered chapter.
+\let\section = \numberedsec
+\let\subsection = \numberedsubsec
+\let\subsubsection = \numberedsubsubsec
+
+% Define @majorheading, @heading and @subheading
+
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+%       1) We use \vbox rather than the earlier \line to permit
+%          overlong headings to fold.
+%       2) \hyphenpenalty is set to 10000 because hyphenation in a
+%          heading is obnoxious; this forbids it.
+%       3) Likewise, headings look best if no \parindent is used, and
+%          if justification is not attempted.  Hence \raggedright.
+
+
+\def\majorheading{%
+  {\advance\chapheadingskip by 10pt \chapbreak }%
+  \parsearg\chapheadingzzz
+}
+
+\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
+\def\chapheadingzzz#1{%
+  {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                    \parindent=0pt\raggedright
+                    \rm #1\hfill}}%
+  \bigskip \par\penalty 200\relax
+  \suppressfirstparagraphindent
+}
+
+% @heading, @subheading, @subsubheading.
+\def\heading{\parsearg\doheading}
+\def\subheading{\parsearg\dosubheading}
+\def\subsubheading{\parsearg\dosubsubheading}
+\def\doheading#1{\sectionheading{#1}{sec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\def\dosubheading#1{\sectionheading{#1}{subsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+\def\dosubsubheading#1{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{}
+  \suppressfirstparagraphindent}
+
+% These macros generate a chapter, section, etc. heading only
+% (including whitespace, linebreaking, etc. around it),
+% given all the information in convenient, parsed form.
+
+%%% Args are the skip and penalty (usually negative)
+\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
+
+\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
+
+%%% Define plain chapter starts, and page on/off switching for it
+% Parameter controlling skip before chapter headings (if needed)
+
+\newskip\chapheadingskip
+
+\def\chapbreak{\dobreak \chapheadingskip {-4000}}
+\def\chappager{\par\vfill\supereject}
+\def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi}
+
+\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
+
+\def\CHAPPAGoff{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chapbreak
+\global\let\pagealignmacro=\chappager}
+
+\def\CHAPPAGon{%
+\global\let\contentsalignmacro = \chappager
+\global\let\pchapsepmacro=\chappager
+\global\let\pagealignmacro=\chappager
+\global\def\HEADINGSon{\HEADINGSsingle}}
+
+\def\CHAPPAGodd{%
+\global\let\contentsalignmacro = \chapoddpage
+\global\let\pchapsepmacro=\chapoddpage
+\global\let\pagealignmacro=\chapoddpage
+\global\def\HEADINGSon{\HEADINGSdouble}}
+
+\CHAPPAGon
+
+\def\CHAPFplain{%
+\global\let\chapmacro=\chfplain
+\global\let\centerchapmacro=\centerchfplain}
+
+% Normal chapter opening.
+% 
+% #1 is the text, #2 is the section type (Ynumbered, Ynothing,
+% Yappendix, Yomitfromtoc), #3 the chapter number.
+% 
+% To test against our argument.
+\def\Ynothingkeyword{Ynothing}
+\def\Yomitfromtockeyword{Yomitfromtoc}
+\def\Yappendixkeyword{Yappendix}
+%
+\def\chfplain#1#2#3{%
+  \pchapsepmacro
+  {%
+    \chapfonts \rm
+    %
+    % Have to define \thissection before calling \donoderef, because the
+    % xref code eventually uses it.  On the other hand, it has to be called
+    % after \pchapsepmacro, or the headline will change too soon.
+    \gdef\thissection{#1}%
+    \gdef\thischaptername{#1}%
+    %
+    % Only insert the separating space if we have a chapter/appendix
+    % number, and don't print the unnumbered ``number''.
+    \def\temptype{#2}%
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unnchap}%
+      \def\thischapter{#1}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      \setbox0 = \hbox{}% contents like unnumbered, but no toc entry
+      \def\toctype{omit}%
+      \xdef\thischapter{}%
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
+      \def\toctype{app}%
+      % We don't substitute the actual chapter name into \thischapter
+      % because we don't want its macros evaluated now.  And we don't
+      % use \thissection because that changes with each section.
+      %
+      \xdef\thischapter{\putwordAppendix{} \appendixletter:
+                        \noexpand\thischaptername}%
+    \else
+      \setbox0 = \hbox{#3\enspace}%
+      \def\toctype{numchap}%
+      \xdef\thischapter{\putwordChapter{} \the\chapno:
+                        \noexpand\thischaptername}%
+    \fi\fi\fi
+    %
+    % Write the toc entry for this chapter.  Must come before the
+    % \donoderef, because we include the current node name in the toc
+    % entry, and \donoderef resets it to empty.
+    \writetocentry{\toctype}{#1}{#3}%
+    %
+    % For pdftex, we have to write out the node definition (aka, make
+    % the pdfdest) after any page break, but before the actual text has
+    % been typeset.  If the destination for the pdf outline is after the
+    % text, then jumping from the outline may wind up with the text not
+    % being visible, for instance under high magnification.
+    \donoderef{#2}%
+    %
+    % Typeset the actual heading.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0 \centerparametersmaybe
+          \unhbox0 #1\par}%
+  }%
+  \nobreak\bigskip % no page break after a chapter title
+  \nobreak
+}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerchfplain#1{{%
+  \def\centerparametersmaybe{%
+    \advance\rightskip by 3\rightskip
+    \leftskip = \rightskip
+    \parfillskip = 0pt
+  }%
+  \chfplain{#1}{Ynothing}{}%
+}}
+
+\CHAPFplain % The default
+
+% I don't think this chapter style is supported any more, so I'm not
+% updating it with the new noderef stuff.  We'll see.  --karl, 11aug03.
+% 
+\def\unnchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt\raggedright
+                       \rm #1\hfill}}\bigskip \par\nobreak
+}
+
+\def\chfopen #1#2{\chapoddpage {\chapfonts
+\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
+\par\penalty 5000 %
+}
+
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+                       \parindent=0pt
+                       \hfill {\rm #1}\hfill}}\bigskip \par\nobreak
+}
+
+\def\CHAPFopen{%
+\global\let\chapmacro=\chfopen
+\global\let\centerchapmacro=\centerchfopen}
+
+
+% Section titles.  These macros combine the section number parts and
+% call the generic \sectionheading to do the printing.
+% 
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
+
+% Subsection titles.
+\newskip\subsecheadingskip
+\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
+
+% Subsubsection titles.
+\def\subsubsecheadingskip{\subsecheadingskip}
+\def\subsubsecheadingbreak{\subsecheadingbreak}
+
+
+% Print any size, any type, section title.
+% 
+% #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is
+% the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the
+% section number.
+% 
+\def\sectionheading#1#2#3#4{%
+  {%
+    % Switch to the right set of fonts.
+    \csname #2fonts\endcsname \rm
+    %
+    % Insert space above the heading.
+    \csname #2headingbreak\endcsname
+    %
+    % Only insert the space after the number if we have a section number.
+    \def\sectionlevel{#2}%
+    \def\temptype{#3}%
+    %
+    \ifx\temptype\Ynothingkeyword
+      \setbox0 = \hbox{}%
+      \def\toctype{unn}%
+      \gdef\thissection{#1}%
+    \else\ifx\temptype\Yomitfromtockeyword
+      % for @headings -- no section number, don't include in toc,
+      % and don't redefine \thissection.
+      \setbox0 = \hbox{}%
+      \def\toctype{omit}%
+      \let\sectionlevel=\empty
+    \else\ifx\temptype\Yappendixkeyword
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{app}%
+      \gdef\thissection{#1}%
+    \else
+      \setbox0 = \hbox{#4\enspace}%
+      \def\toctype{num}%
+      \gdef\thissection{#1}%
+    \fi\fi\fi
+    %
+    % Write the toc entry (before \donoderef).  See comments in \chfplain.
+    \writetocentry{\toctype\sectionlevel}{#1}{#4}%
+    %
+    % Write the node reference (= pdf destination for pdftex).
+    % Again, see comments in \chfplain.
+    \donoderef{#3}%
+    %
+    % Output the actual section heading.
+    \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+          \hangindent=\wd0  % zero if no section number
+          \unhbox0 #1}%
+  }%
+  % Add extra space after the heading -- half of whatever came above it.
+  % Don't allow stretch, though.
+  \kern .5 \csname #2headingskip\endcsname
+  %
+  % Do not let the kern be a potential breakpoint, as it would be if it
+  % was followed by glue.
+  \nobreak
+  %
+  % We'll almost certainly start a paragraph next, so don't let that
+  % glue accumulate.  (Not a breakpoint because it's preceded by a
+  % discardable item.)
+  \vskip-\parskip
+  %
+  % This \nobreak is purely so the last item on the list is a \penalty
+  % of 10000.  This is so other code, for instance \parsebodycommon, can
+  % check for and avoid allowing breakpoints.  Otherwise, it would
+  % insert a valid breakpoint between:
+  %   @section sec-whatever
+  %   @deffn def-whatever
+  \nobreak
+}
+
+
+\message{toc,}
+% Table of contents.
+\newwrite\tocfile
+
+% Write an entry to the toc file, opening it if necessary.
+% Called from @chapter, etc.  
+% 
+% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno}
+% We append the current node name (if any) and page number as additional
+% arguments for the \{chap,sec,...}entry macros which will eventually
+% read this.  The node name is used in the pdf outlines as the
+% destination to jump to.
+% 
+% We open the .toc file for writing here instead of at @setfilename (or
+% any other fixed time) so that @contents can be anywhere in the document.
+% But if #1 is `omit', then we don't do anything.  This is used for the
+% table of contents chapter openings themselves.
+%
+\newif\iftocfileopened
+\def\omitkeyword{omit}%
+%
+\def\writetocentry#1#2#3{%
+  \edef\writetoctype{#1}%
+  \ifx\writetoctype\omitkeyword \else
+    \iftocfileopened\else
+      \immediate\openout\tocfile = \jobname.toc
+      \global\tocfileopenedtrue
+    \fi
+    %
+    \iflinks
+      \toks0 = {#2}%
+      \toks2 = \expandafter{\lastnode}%
+      \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}%
+                               {\the\toks2}{\noexpand\folio}}}%
+      \temp
+    \fi
+  \fi
+  %
+  % Tell \shipout to create a pdf destination on each page, if we're
+  % writing pdf.  These are used in the table of contents.  We can't
+  % just write one on every page because the title pages are numbered
+  % 1 and 2 (the page numbers aren't printed), and so are the first
+  % two pages of the document.  Thus, we'd have two destinations named
+  % `1', and two named `2'.
+  \ifpdf \global\pdfmakepagedesttrue \fi
+}
+
+\newskip\contentsrightmargin \contentsrightmargin=1in
+\newcount\savepageno
+\newcount\lastnegativepageno \lastnegativepageno = -1
+
+% Prepare to read what we've written to \tocfile.
+%
+\def\startcontents#1{%
+   % If @setchapternewpage on, and @headings double, the contents should
+   % start on an odd page, unlike chapters.  Thus, we maintain
+   % \contentsalignmacro in parallel with \pagealignmacro.
+   % From: Torbjorn Granlund <tege@matematik.su.se>
+   \contentsalignmacro
+   \immediate\closeout\tocfile
+   %
+   % Don't need to put `Contents' or `Short Contents' in the headline.
+   % It is abundantly clear what they are.
+   \def\thischapter{}%
+   \chapmacro{#1}{Yomitfromtoc}{}%
+   %
+   \savepageno = \pageno
+   \begingroup                  % Set up to handle contents files properly.
+      \catcode`\\=0  \catcode`\{=1  \catcode`\}=2  \catcode`\@=11
+      % We can't do this, because then an actual ^ in a section
+      % title fails, e.g., @chapter ^ -- exponentiation.  --karl, 9jul97.
+      %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+      \raggedbottom             % Worry more about breakpoints than the bottom.
+      \advance\hsize by -\contentsrightmargin % Don't use the full line length.
+      %
+      % Roman numerals for page numbers.
+      \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
+}
+
+
+% Normal (long) toc.
+\def\contents{%
+   \startcontents{\putwordTOC}%
+     \openin 1 \jobname.toc
+     \ifeof 1 \else
+       \closein 1
+       \input \jobname.toc
+     \fi
+     \vfill \eject
+     \contentsalignmacro % in case @setchapternewpage odd is in effect
+     \pdfmakeoutlines
+   \endgroup
+   \lastnegativepageno = \pageno
+   \global\pageno = \savepageno
+}
+
+% And just the chapters.
+\def\summarycontents{%
+   \startcontents{\putwordShortTOC}%
+      %
+      \let\numchapentry = \shortchapentry
+      \let\appentry = \shortchapentry
+      \let\unnchapentry = \shortunnchapentry
+      % We want a true roman here for the page numbers.
+      \secfonts
+      \let\rm=\shortcontrm \let\bf=\shortcontbf
+      \let\sl=\shortcontsl \let\tt=\shortconttt
+      \rm
+      \hyphenpenalty = 10000
+      \advance\baselineskip by 1pt % Open it up a little.
+      \def\numsecentry##1##2##3##4{}
+      \let\appsecentry = \numsecentry
+      \let\unnsecentry = \numsecentry
+      \let\numsubsecentry = \numsecentry
+      \let\appsubsecentry = \numsecentry
+      \let\unnsubsecentry = \numsecentry
+      \let\numsubsubsecentry = \numsecentry
+      \let\appsubsubsecentry = \numsecentry
+      \let\unnsubsubsecentry = \numsecentry
+      \openin 1 \jobname.toc
+      \ifeof 1 \else
+        \closein 1
+        \input \jobname.toc
+      \fi
+     \vfill \eject
+     \contentsalignmacro % in case @setchapternewpage odd is in effect
+   \endgroup
+   \lastnegativepageno = \pageno
+   \global\pageno = \savepageno
+}
+\let\shortcontents = \summarycontents
+
+% Typeset the label for a chapter or appendix for the short contents.
+% The arg is, e.g., `A' for an appendix, or `3' for a chapter.
+%
+\def\shortchaplabel#1{%
+  % This space should be enough, since a single number is .5em, and the
+  % widest letter (M) is 1em, at least in the Computer Modern fonts.
+  % But use \hss just in case.
+  % (This space doesn't include the extra space that gets added after
+  % the label; that gets put in by \shortchapentry above.)
+  % 
+  % We'd like to right-justify chapter numbers, but that looks strange
+  % with appendix letters.  And right-justifying numbers and
+  % left-justifying letters looks strange when there is less than 10
+  % chapters.  Have to read the whole toc once to know how many chapters
+  % there are before deciding ...
+  \hbox to 1em{#1\hss}%
+}
+
+% These macros generate individual entries in the table of contents.
+% The first argument is the chapter or section name.
+% The last argument is the page number.
+% The arguments in between are the chapter number, section number, ...
+
+% Chapters, in the main contents.
+\def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}}
+%
+% Chapters, in the short toc.
+% See comments in \dochapentry re vbox and related settings.
+\def\shortchapentry#1#2#3#4{%
+  \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}%
+}
+
+% Appendices, in the main contents.
+% Need the word Appendix, and a fixed-size box.
+% 
+\def\appendixbox#1{%
+  % We use M since it's probably the widest letter.
+  \setbox0 = \hbox{\putwordAppendix{} M}%
+  \hbox to \wd0{\putwordAppendix{} #1\hss}}
+%
+\def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}}
+
+% Unnumbered chapters.
+\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}}
+\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}}
+
+% Sections.
+\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}}
+\let\appsecentry=\numsecentry
+\def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}}
+
+% Subsections.
+\def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsecentry=\numsubsecentry
+\def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}}
+
+% And subsubsections.
+\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}}
+\let\appsubsubsecentry=\numsubsubsecentry
+\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}}
+
+% This parameter controls the indentation of the various levels.
+\newdimen\tocindent \tocindent = 2pc
+
+% Now for the actual typesetting. In all these, #1 is the text and #2 is the
+% page number.
+%
+% If the toc has to be broken over pages, we want it to be at chapters
+% if at all possible; hence the \penalty.
+\def\dochapentry#1#2{%
+   \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
+   \begingroup
+     \chapentryfonts
+     \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+   \endgroup
+   \nobreak\vskip .25\baselineskip plus.1\baselineskip
+}
+
+\def\dosecentry#1#2{\begingroup
+  \secentryfonts \leftskip=\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsecentry#1#2{\begingroup
+  \subsecentryfonts \leftskip=2\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+\def\dosubsubsecentry#1#2{\begingroup
+  \subsubsecentryfonts \leftskip=3\tocindent
+  \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+\endgroup}
+
+% Final typesetting of a toc entry; we use the same \entry macro as for
+% the index entries, but we want to suppress hyphenation here.  (We
+% can't do that in the \entry macro, since index entries might consist
+% of hyphenated-identifiers-that-do-not-fit-on-a-line-and-nothing-else.)
+\def\tocentry#1#2{\begingroup
+  \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
+  % Do not use \turnoffactive in these arguments.  Since the toc is
+  % typeset in cmr, characters such as _ would come out wrong; we
+  % have to do the usual translation tricks.
+  \entry{#1}{#2}%
+\endgroup}
+
+% Space between chapter (or whatever) number and the title.
+\def\labelspace{\hskip1em \relax}
+
+\def\dopageno#1{{\rm #1}}
+\def\doshortpageno#1{{\rm #1}}
+
+\def\chapentryfonts{\secfonts \rm}
+\def\secentryfonts{\textfonts}
+\def\subsecentryfonts{\textfonts}
+\def\subsubsecentryfonts{\textfonts}
+
+
+\message{environments,}
+% @foo ... @end foo.
+
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
+%
+% Since these characters are used in examples, it should be an even number of
+% \tt widths. Each \tt character is 1en, so two makes it 1em.
+%
+\def\point{$\star$}
+\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
+\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
+\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
+\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
+
+% The @error{} command.
+% Adapted from the TeXbook's \boxit.
+%
+\newbox\errorbox
+%
+{\tentt \global\dimen0 = 3em}% Width of the box.
+\dimen2 = .55pt % Thickness of rules
+% The text. (`r' is open on the right, `e' somewhat less so on the left.)
+\setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt}
+%
+\global\setbox\errorbox=\hbox to \dimen0{\hfil
+   \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
+   \advance\hsize by -2\dimen2 % Rules.
+   \vbox{
+      \hrule height\dimen2
+      \hbox{\vrule width\dimen2 \kern3pt          % Space to left of text.
+         \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
+         \kern3pt\vrule width\dimen2}% Space to right.
+      \hrule height\dimen2}
+    \hfil}
+%
+\def\error{\leavevmode\lower.7ex\copy\errorbox}
+
+% @tex ... @end tex    escapes into raw Tex temporarily.
+% One exception: @ is still an escape character, so that @end tex works.
+% But \@ or @@ will get a plain tex @ character.
+
+\def\tex{\begingroup
+  \catcode `\\=0 \catcode `\{=1 \catcode `\}=2
+  \catcode `\$=3 \catcode `\&=4 \catcode `\#=6
+  \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
+  \catcode `\%=14
+  \catcode `\+=\other
+  \catcode `\"=\other
+  \catcode `\==\other
+  \catcode `\|=\other
+  \catcode `\<=\other
+  \catcode `\>=\other
+  \escapechar=`\\
+  %
+  \let\b=\ptexb
+  \let\bullet=\ptexbullet
+  \let\c=\ptexc
+  \let\,=\ptexcomma
+  \let\.=\ptexdot
+  \let\dots=\ptexdots
+  \let\equiv=\ptexequiv
+  \let\!=\ptexexclam
+  \let\i=\ptexi
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \let\{=\ptexlbrace
+  \let\+=\tabalign
+  \let\}=\ptexrbrace
+  \let\/=\ptexslash
+  \let\*=\ptexstar
+  \let\t=\ptext
+  %
+  \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+  \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
+  \def\@{@}%
+\let\Etex=\endgroup}
+
+% Define @lisp ... @end lisp.
+% @lisp does a \begingroup so it can rebind things,
+% including the definition of @end lisp (which normally is erroneous).
+
+% Amount to narrow the margins by for @lisp.
+\newskip\lispnarrowing \lispnarrowing=0.4in
+
+% This is the definition that ^^M gets inside @lisp, @example, and other
+% such environments.  \null is better than a space, since it doesn't
+% have any width.
+\def\lisppar{\null\endgraf}
+
+% Make each space character in the input produce a normal interword
+% space in the output.  Don't allow a line break at this space, as this
+% is used only in environments like @example, where each line of input
+% should produce a line of output anyway.
+%
+{\obeyspaces %
+\gdef\sepspaces{\obeyspaces\let =\tie}}
+
+% Define \obeyedspace to be our active space, whatever it is.  This is
+% for use in \parsearg.
+{\sepspaces%
+\global\let\obeyedspace= }
+
+% This space is always present above and below environments.
+\newskip\envskipamount \envskipamount = 0pt
+
+% Make spacing and below environment symmetrical.  We use \parskip here
+% to help in doing that, since in @example-like environments \parskip
+% is reset to zero; thus the \afterenvbreak inserts no space -- but the
+% start of the next paragraph will insert \parskip.
+%
+\def\aboveenvbreak{{%
+  % =10000 instead of <10000 because of a special case in \itemzzz, q.v.
+  \ifnum \lastpenalty=10000 \else
+    \advance\envskipamount by \parskip
+    \endgraf
+    \ifdim\lastskip<\envskipamount
+      \removelastskip
+      % it's not a good place to break if the last penalty was \nobreak
+      % or better ...
+      \ifnum\lastpenalty>10000 \else \penalty-50 \fi
+      \vskip\envskipamount
+    \fi
+  \fi
+}}
+
+\let\afterenvbreak = \aboveenvbreak
+
+% \nonarrowing is a flag.  If "set", @lisp etc don't narrow margins.
+\let\nonarrowing=\relax
+
+% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
+% environment contents.
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
+%
+\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
+\def\ctr{{\hskip 6pt\circle\char'010}}
+\def\cbl{{\circle\char'012\hskip -6pt}}
+\def\cbr{{\hskip 6pt\circle\char'011}}
+\def\carttop{\hbox to \cartouter{\hskip\lskip
+        \ctl\leaders\hrule height\circthick\hfil\ctr
+        \hskip\rskip}}
+\def\cartbot{\hbox to \cartouter{\hskip\lskip
+        \cbl\leaders\hrule height\circthick\hfil\cbr
+        \hskip\rskip}}
+%
+\newskip\lskip\newskip\rskip
+
+\def\cartouche{%
+\par  % can't be in the midst of a paragraph.
+\begingroup
+        \lskip=\leftskip \rskip=\rightskip
+        \leftskip=0pt\rightskip=0pt %we want these *outside*.
+        \cartinner=\hsize \advance\cartinner by-\lskip
+                          \advance\cartinner by-\rskip
+        \cartouter=\hsize
+        \advance\cartouter by 18.4pt % allow for 3pt kerns on either
+%                                    side, and for 6pt waste from
+%                                    each corner char, and rule thickness
+        \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+        % Flag to tell @lisp, etc., not to narrow margin.
+        \let\nonarrowing=\comment
+        \vbox\bgroup
+                \baselineskip=0pt\parskip=0pt\lineskip=0pt
+                \carttop
+                \hbox\bgroup
+                        \hskip\lskip
+                        \vrule\kern3pt
+                        \vbox\bgroup
+                                \hsize=\cartinner
+                                \kern3pt
+                                \begingroup
+                                        \baselineskip=\normbskip
+                                        \lineskip=\normlskip
+                                        \parskip=\normpskip
+                                        \vskip -\parskip
+\def\Ecartouche{%
+                                \endgroup
+                                \kern3pt
+                        \egroup
+                        \kern3pt\vrule
+                        \hskip\rskip
+                \egroup
+                \cartbot
+        \egroup
+\endgroup
+}}
+
+
+% This macro is called at the beginning of all the @example variants,
+% inside a group.
+\def\nonfillstart{%
+  \aboveenvbreak
+  \inENV % This group ends at the end of the body
+  \hfuzz = 12pt % Don't be fussy
+  \sepspaces % Make spaces be word-separators rather than space tokens.
+  \let\par = \lisppar % don't ignore blank lines
+  \obeylines % each line of input is a line of output
+  \parskip = 0pt
+  \parindent = 0pt
+  \emergencystretch = 0pt % don't try to avoid overfull boxes
+  % @cartouche defines \nonarrowing to inhibit narrowing
+  % at next level down.
+  \ifx\nonarrowing\relax
+    \advance \leftskip by \lispnarrowing
+    \exdentamount=\lispnarrowing
+    \let\exdent=\nofillexdent
+    \let\nonarrowing=\relax
+  \fi
+}
+
+% Define the \E... control sequence only if we are inside the particular
+% environment, so the error checking in \end will work.
+%
+% To end an @example-like environment, we first end the paragraph (via
+% \afterenvbreak's vertical glue), and then the group.  That way we keep
+% the zero \parskip that the environments set -- \parskip glue will be
+% inserted at the beginning of the next paragraph in the document, after
+% the environment.
+%
+\def\nonfillfinish{\afterenvbreak\endgroup}
+
+% @lisp: indented, narrowed, typewriter font.
+\def\lisp{\begingroup
+  \nonfillstart
+  \let\Elisp = \nonfillfinish
+  \tt
+  \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
+  \gobble       % eat return
+}
+
+% @example: Same as @lisp.
+\def\example{\begingroup \def\Eexample{\nonfillfinish\endgroup}\lisp}
+
+% @smallexample and @smalllisp: use smaller fonts.
+% Originally contributed by Pavel@xerox.
+\def\smalllisp{\begingroup
+  \def\Esmalllisp{\nonfillfinish\endgroup}%
+  \def\Esmallexample{\nonfillfinish\endgroup}%
+  \smallexamplefonts
+  \lisp
+}
+\let\smallexample = \smalllisp
+
+
+% @display: same as @lisp except keep current font.
+%
+\def\display{\begingroup
+  \nonfillstart
+  \let\Edisplay = \nonfillfinish
+  \gobble
+}
+%
+% @smalldisplay: @display plus smaller fonts.
+%
+\def\smalldisplay{\begingroup
+  \def\Esmalldisplay{\nonfillfinish\endgroup}%
+  \smallexamplefonts \rm
+  \display
+}
+
+% @format: same as @display except don't narrow margins.
+%
+\def\format{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \let\Eformat = \nonfillfinish
+  \gobble
+}
+%
+% @smallformat: @format plus smaller fonts.
+%
+\def\smallformat{\begingroup
+  \def\Esmallformat{\nonfillfinish\endgroup}%
+  \smallexamplefonts \rm
+  \format
+}
+
+% @flushleft (same as @format).
+%
+\def\flushleft{\begingroup \def\Eflushleft{\nonfillfinish\endgroup}\format}
+
+% @flushright.
+%
+\def\flushright{\begingroup
+  \let\nonarrowing = t
+  \nonfillstart
+  \let\Eflushright = \nonfillfinish
+  \advance\leftskip by 0pt plus 1fill
+  \gobble
+}
+
+
+% @quotation does normal linebreaking (hence we can't use \nonfillstart)
+% and narrows the margins.
+%
+\def\quotation{%
+  \begingroup\inENV %This group ends at the end of the @quotation body
+  {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+  \parindent=0pt
+  % We have retained a nonzero parskip for the environment, since we're
+  % doing normal filling. So to avoid extra space below the environment...
+  \def\Equotation{\parskip = 0pt \nonfillfinish}%
+  %
+  % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
+  \ifx\nonarrowing\relax
+    \advance\leftskip by \lispnarrowing
+    \advance\rightskip by \lispnarrowing
+    \exdentamount = \lispnarrowing
+    \let\nonarrowing = \relax
+  \fi
+}
+
+
+% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>}
+% If we want to allow any <char> as delimiter,
+% we need the curly braces so that makeinfo sees the @verb command, eg:
+% `@verbx...x' would look like the '@verbx' command.  --janneke@gnu.org
+%
+% [Knuth]: Donald Ervin Knuth, 1996.  The TeXbook.
+%
+% [Knuth] p.344; only we need to do the other characters Texinfo sets
+% active too.  Otherwise, they get lost as the first character on a
+% verbatim line.
+\def\dospecials{%
+  \do\ \do\\\do\{\do\}\do\$\do\&%
+  \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
+  \do\<\do\>\do\|\do\@\do+\do\"%
+}
+%
+% [Knuth] p. 380
+\def\uncatcodespecials{%
+  \def\do##1{\catcode`##1=12}\dospecials}
+%
+% [Knuth] pp. 380,381,391
+% Disable Spanish ligatures ?` and !` of \tt font
+\begingroup
+  \catcode`\`=\active\gdef`{\relax\lq}
+\endgroup
+%
+% Setup for the @verb command.
+%
+% Eight spaces for a tab
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }}
+\endgroup
+%
+\def\setupverb{%
+  \tt  % easiest (and conventionally used) font for verbatim
+  \def\par{\leavevmode\endgraf}%
+  \catcode`\`=\active
+  \tabeightspaces
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+}
+
+% Setup for the @verbatim environment
+%
+% Real tab expansion
+\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
+%
+\def\starttabbox{\setbox0=\hbox\bgroup}
+\begingroup
+  \catcode`\^^I=\active
+  \gdef\tabexpand{%
+    \catcode`\^^I=\active
+    \def^^I{\leavevmode\egroup
+      \dimen0=\wd0 % the width so far, or since the previous tab
+      \divide\dimen0 by\tabw
+      \multiply\dimen0 by\tabw % compute previous multiple of \tabw
+      \advance\dimen0 by\tabw  % advance to next multiple of \tabw
+      \wd0=\dimen0 \box0 \starttabbox
+    }%
+  }
+\endgroup
+\def\setupverbatim{%
+  % Easiest (and conventionally used) font for verbatim
+  \tt
+  \def\par{\leavevmode\egroup\box0\endgraf}%
+  \catcode`\`=\active
+  \tabexpand
+  % Respect line breaks,
+  % print special symbols as themselves, and
+  % make each space count
+  % must do in this order:
+  \obeylines \uncatcodespecials \sepspaces
+  \everypar{\starttabbox}%
+}
+
+% Do the @verb magic: verbatim text is quoted by unique
+% delimiter characters.  Before first delimiter expect a
+% right brace, after last delimiter expect closing brace:
+%
+%    \def\doverb'{'<char>#1<char>'}'{#1}
+%
+% [Knuth] p. 382; only eat outer {}
+\begingroup
+  \catcode`[=1\catcode`]=2\catcode`\{=12\catcode`\}=12
+  \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next]
+\endgroup
+%
+\def\verb{\begingroup\setupverb\doverb}
+%
+%
+% Do the @verbatim magic: define the macro \doverbatim so that
+% the (first) argument ends when '@end verbatim' is reached, ie:
+%
+%     \def\doverbatim#1@end verbatim{#1}
+%
+% For Texinfo it's a lot easier than for LaTeX,
+% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
+% we need not redefine '\', '{' and '}'.
+%
+% Inspired by LaTeX's verbatim command set [latex.ltx]
+%% Include LaTeX hack for completeness -- never know
+%% \begingroup
+%% \catcode`|=0 \catcode`[=1
+%% \catcode`]=2\catcode`\{=12\catcode`\}=12\catcode`\ =\active
+%% \catcode`\\=12|gdef|doverbatim#1@end verbatim[
+%% #1|endgroup|def|Everbatim[]|end[verbatim]]
+%% |endgroup
+%
+\begingroup
+  \catcode`\ =\active
+  \obeylines %
+  % ignore everything up to the first ^^M, that's the newline at the end
+  % of the @verbatim input line itself.  Otherwise we get an extra blank
+  % line in the output.
+  \gdef\doverbatim#1^^M#2@end verbatim{#2\end{verbatim}}%
+\endgroup
+%
+\def\verbatim{%
+  \def\Everbatim{\nonfillfinish\endgroup}%
+  \begingroup
+    \nonfillstart
+    \advance\leftskip by -\defbodyindent
+    \begingroup\setupverbatim\doverbatim
+}
+
+% @verbatiminclude FILE - insert text of file in verbatim environment.
+%
+% Allow normal characters that we make active in the argument (a file name).
+\def\verbatiminclude{%
+  \begingroup
+    \catcode`\\=\other
+    \catcode`~=\other
+    \catcode`^=\other
+    \catcode`_=\other
+    \catcode`|=\other
+    \catcode`<=\other
+    \catcode`>=\other
+    \catcode`+=\other
+    \parsearg\doverbatiminclude
+}
+\def\setupverbatiminclude{%
+  \begingroup
+    \nonfillstart
+    \advance\leftskip by -\defbodyindent
+    \begingroup\setupverbatim
+}
+%
+\def\doverbatiminclude#1{%
+     % Restore active chars for included file.
+  \endgroup
+  \begingroup
+    \let\value=\expandablevalue
+    \def\thisfile{#1}%
+    \expandafter\expandafter\setupverbatiminclude\input\thisfile
+  \endgroup
+  \nonfillfinish
+  \endgroup
+}
+
+% @copying ... @end copying.
+% Save the text away for @insertcopying later.  Many commands won't be
+% allowed in this context, but that's ok.
+%
+% We save the uninterpreted tokens, rather than creating a box.
+% Saving the text in a box would be much easier, but then all the
+% typesetting commands (@smallbook, font changes, etc.) have to be done
+% beforehand -- and a) we want @copying to be done first in the source
+% file; b) letting users define the frontmatter in as flexible order as
+% possible is very desirable.
+%
+\def\copying{\begingroup
+  % Define a command to swallow text until we reach `@end copying'.
+  % \ is the escape char in this texinfo.tex file, so it is the
+  % delimiter for the command; @ will be the escape char when we read
+  % it, but that doesn't matter.
+  \long\def\docopying##1\end copying{\gdef\copyingtext{##1}\enddocopying}%
+  %
+  % We must preserve ^^M's in the input file; see \insertcopying below.
+  \catcode`\^^M = \active
+  \docopying
+}
+
+% What we do to finish off the copying text.
+%
+\def\enddocopying{\endgroup\ignorespaces}
+
+% @insertcopying.  Here we must play games with ^^M's.  On the one hand,
+% we need them to delimit commands such as `@end quotation', so they
+% must be active.  On the other hand, we certainly don't want every
+% end-of-line to be a \par, as would happen with the normal active
+% definition of ^^M.  On the third hand, two ^^M's in a row should still
+% generate a \par.
+%
+% Our approach is to make ^^M insert a space and a penalty1 normally;
+% then it can also check if \lastpenalty=1.  If it does, then manually
+% do \par.
+%
+% This messes up the normal definitions of @c[omment], so we redefine
+% it.  Similarly for @ignore.  (These commands are used in the gcc
+% manual for man page generation.)
+%
+% Seems pretty fragile, most line-oriented commands will presumably
+% fail, but for the limited use of getting the copying text (which
+% should be quite simple) inserted, we can hope it's ok.
+%
+{\catcode`\^^M=\active %
+\gdef\insertcopying{\begingroup %
+  \parindent = 0pt  % looks wrong on title page
+  \def^^M{%
+    \ifnum \lastpenalty=1 %
+      \par %
+    \else %
+      \space \penalty 1 %
+    \fi %
+  }%
+  %
+  % Fix @c[omment] for catcode 13 ^^M's.
+  \def\c##1^^M{\ignorespaces}%
+  \let\comment = \c %
+  %
+  % Don't bother jumping through all the hoops that \doignore does, it
+  % would be very hard since the catcodes are already set.
+  \long\def\ignore##1\end ignore{\ignorespaces}%
+  %
+  \copyingtext %
+\endgroup}%
+}
+
+\message{defuns,}
+% @defun etc.
+
+\newskip\defbodyindent \defbodyindent=.4in
+\newskip\defargsindent \defargsindent=50pt
+\newskip\deflastargmargin \deflastargmargin=18pt
+
+\newcount\parencount
+
+% We want ()&[] to print specially on the defun line.
+%
+\def\activeparens{%
+  \catcode`\(=\active \catcode`\)=\active
+  \catcode`\&=\active
+  \catcode`\[=\active \catcode`\]=\active
+}
+
+% Make control sequences which act like normal parenthesis chars.
+\let\lparen = ( \let\rparen = )
+
+{\activeparens % Now, smart parens don't turn on until &foo (see \amprm)
+
+% Be sure that we always have a definition for `(', etc.  For example,
+% if the fn name has parens in it, \boldbrax will not be in effect yet,
+% so TeX would otherwise complain about undefined control sequence.
+\global\let(=\lparen \global\let)=\rparen
+\global\let[=\lbrack \global\let]=\rbrack
+
+\gdef\functionparens{\boldbrax\let&=\amprm\parencount=0 }
+\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
+% This is used to turn on special parens
+% but make & act ordinary (given that it's active).
+\gdef\boldbraxnoamp{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb\let&=\ampnr}
+
+% Definitions of (, ) and & used in args for functions.
+% This is the definition of ( outside of all parentheses.
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested
+  \global\advance\parencount by 1
+}
+%
+% This is the definition of ( when already inside a level of parens.
+\gdef\opnested{\char`\(\global\advance\parencount by 1 }
+%
+\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
+  % also in that case restore the outer-level definition of (.
+  \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+  \global\advance \parencount by -1 }
+% If we encounter &foo, then turn on ()-hacking afterwards
+\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
+%
+\gdef\normalparens{\boldbrax\let&=\ampnr}
+} % End of definition inside \activeparens
+%% These parens (in \boldbrax) actually are a little bolder than the
+%% contained text.  This is especially needed for [ and ]
+\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 }
+\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 }
+\let\ampnr = \&
+\def\lbrb{{\bf\char`\[}}
+\def\rbrb{{\bf\char`\]}}
+
+% Active &'s sneak into the index arguments, so make sure it's defined.
+{
+  \catcode`& = \active
+  \global\let& = \ampnr
+}
+
+% \defname, which formats the name of the @def (not the args).
+% #1 is the function name.
+% #2 is the type of definition, such as "Function".
+%
+\def\defname#1#2{%
+  % How we'll output the type name.  Putting it in brackets helps
+  % distinguish it from the body text that may end up on the next line
+  % just below it.
+  \def\temp{#2}%
+  \ifx\temp\empty
+    \def\defnametype{}%
+  \else
+    \def\defnametype{[\rm #2]}%
+  \fi
+  %
+  % Get the values of \leftskip and \rightskip as they were outside the @def...
+  \dimen2=\leftskip
+  \advance\dimen2 by -\defbodyindent
+  %
+  % Figure out values for the paragraph shape.
+  \setbox0=\hbox{\hskip \deflastargmargin{\defnametype}}%
+  \dimen0=\hsize \advance \dimen0 by -\wd0  % compute size for first line
+  \dimen1=\hsize \advance \dimen1 by -\defargsindent  % size for continuations
+  \parshape 2 0in \dimen0 \defargsindent \dimen1
+  %
+  % Output arg 2 ("Function" or some such) but stuck inside a box of
+  % width 0 so it does not interfere with linebreaking.
+  \noindent
+  %
+  {% Adjust \hsize to exclude the ambient margins,
+   % so that \rightline will obey them.
+   \advance \hsize by -\dimen2
+   \dimen3 = 0pt  % was -1.25pc
+   \rlap{\rightline{\defnametype\kern\dimen3}}%
+  }%
+  %
+  % Allow all lines to be underfull without complaint:
+  \tolerance=10000 \hbadness=10000
+  \advance\leftskip by -\defbodyindent
+  \exdentamount=\defbodyindent
+  {\df #1}\enskip        % output function name
+  % \defunargs will be called next to output the arguments, if any.
+}
+
+% Common pieces to start any @def...
+% #1 is the \E... control sequence to end the definition (which we define).
+% #2 is the \...x control sequence (which our caller defines).
+% #3 is the control sequence to process the header, such as \defunheader.
+%
+\def\parsebodycommon#1#2#3{%
+  \begingroup\inENV
+  % If there are two @def commands in a row, we'll have a \nobreak,
+  % which is there to keep the function description together with its
+  % header.  But if there's nothing but headers, we need to allow a
+  % break somewhere.  Check for penalty 10002 (inserted by
+  % \defargscommonending) instead of 10000, since the sectioning
+  % commands insert a \penalty10000, and we don't want to allow a break
+  % between a section heading and a defun.
+  \ifnum\lastpenalty=10002 \penalty2000 \fi
+  %
+  % Similarly, after a section heading, do not allow a break.
+  % But do insert the glue.
+  \ifnum\lastpenalty<10000 \medbreak
+  \else \medskip  % preceded by discardable penalty, so not a breakpoint
+  \fi
+  %
+  % Define the \E... end token that this defining construct specifies
+  % so that it will exit this group.
+  \def#1{\endgraf\endgroup\medbreak}%
+  %
+  \parindent=0in
+  \advance\leftskip by \defbodyindent
+  \exdentamount=\defbodyindent
+}
+
+% Common part of the \...x definitions.
+%
+\def\defxbodycommon{%
+  % As with \parsebodycommon above, allow line break if we have multiple
+  % x headers in a row.  It's not a great place, though.
+  \ifnum\lastpenalty=10002 \penalty2000 \fi
+  %
+  \begingroup\obeylines
+}
+
+% Process body of @defun, @deffn, @defmac, etc.
+%
+\def\defparsebody#1#2#3{%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2{\defxbodycommon \activeparens \spacesplit#3}%
+  \catcode\equalChar=\active
+  \begingroup\obeylines\activeparens
+  \spacesplit#3%
+}
+
+% #1, #2, #3 are the common arguments (see \parsebodycommon above).
+% #4, delimited by the space, is the class name.
+%
+\def\defmethparsebody#1#2#3#4 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2##1 {\defxbodycommon \activeparens \spacesplit{#3{##1}}}%
+  \begingroup\obeylines\activeparens
+  % The \empty here prevents misinterpretation of a construct such as
+  %   @deffn {whatever} {Enharmonic comma}
+  % See comments at \deftpparsebody, although in our case we don't have
+  % to remove the \empty afterwards, since it is empty.
+  \spacesplit{#3{#4}}\empty
+}
+
+% Used for @deftypemethod and @deftypeivar.
+% #1, #2, #3 are the common arguments (see \defparsebody).
+% #4, delimited by a space, is the class name.
+% #5 is the method's return type.
+%
+\def\deftypemethparsebody#1#2#3#4 #5 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2##1 ##2 {\defxbodycommon \activeparens \spacesplit{#3{##1}{##2}}}%
+  \begingroup\obeylines\activeparens
+  \spacesplit{#3{#4}{#5}}%
+}
+
+% Used for @deftypeop.  The change from \deftypemethparsebody is an
+% extra argument at the beginning which is the `category', instead of it
+% being the hardwired string `Method' or `Instance Variable'.  We have
+% to account for this both in the \...x definition and in parsing the
+% input at hand.  Thus also need a control sequence (passed as #5) for
+% the \E... definition to assign the category name to.
+%
+\def\deftypeopparsebody#1#2#3#4#5 #6 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2##1 ##2 ##3 {\def#4{##1}%
+    \defxbodycommon \activeparens \spacesplit{#3{##2}{##3}}}%
+  \begingroup\obeylines\activeparens
+  \spacesplit{#3{#5}{#6}}%
+}
+
+% For @defop.
+\def\defopparsebody #1#2#3#4#5 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2##1 ##2 {\def#4{##1}%
+    \defxbodycommon \activeparens \spacesplit{#3{##2}}}%
+  \begingroup\obeylines\activeparens
+  \spacesplit{#3{#5}}%
+}
+
+% These parsing functions are similar to the preceding ones
+% except that they do not make parens into active characters.
+% These are used for "variables" since they have no arguments.
+%
+\def\defvarparsebody #1#2#3{%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2{\defxbodycommon \spacesplit#3}%
+  \catcode\equalChar=\active
+  \begingroup\obeylines
+  \spacesplit#3%
+}
+
+% @defopvar.
+\def\defopvarparsebody #1#2#3#4#5 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2##1 ##2 {\def#4{##1}%
+    \defxbodycommon \spacesplit{#3{##2}}}%
+  \begingroup\obeylines
+  \spacesplit{#3{#5}}%
+}
+
+\def\defvrparsebody#1#2#3#4 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}%
+  \begingroup\obeylines
+  \spacesplit{#3{#4}}%
+}
+
+% This loses on `@deftp {Data Type} {struct termios}' -- it thinks the
+% type is just `struct', because we lose the braces in `{struct
+% termios}' when \spacesplit reads its undelimited argument.  Sigh.
+% \let\deftpparsebody=\defvrparsebody
+%
+% So, to get around this, we put \empty in with the type name.  That
+% way, TeX won't find exactly `{...}' as an undelimited argument, and
+% won't strip off the braces.
+%
+\def\deftpparsebody #1#2#3#4 {%
+  \parsebodycommon{#1}{#2}{#3}%
+  \def#2##1 {\defxbodycommon \spacesplit{#3{##1}}}%
+  \begingroup\obeylines
+  \spacesplit{\parsetpheaderline{#3{#4}}}\empty
+}
+
+% Fine, but then we have to eventually remove the \empty *and* the
+% braces (if any).  That's what this does.
+%
+\def\removeemptybraces\empty#1\relax{#1}
+
+% After \spacesplit has done its work, this is called -- #1 is the final
+% thing to call, #2 the type name (which starts with \empty), and #3
+% (which might be empty) the arguments.
+%
+\def\parsetpheaderline#1#2#3{%
+  #1{\removeemptybraces#2\relax}{#3}%
+}%
+
+% Split up #2 (the rest of the input line) at the first space token.
+% call #1 with two arguments:
+%  the first is all of #2 before the space token,
+%  the second is all of #2 after that space token.
+% If #2 contains no space token, all of it is passed as the first arg
+% and the second is passed as empty.
+%
+{\obeylines %
+ \gdef\spacesplit#1#2^^M{\endgroup\spacesplitx{#1}#2 \relax\spacesplitx}%
+ \long\gdef\spacesplitx#1#2 #3#4\spacesplitx{%
+   \ifx\relax #3%
+     #1{#2}{}%
+   \else %
+     #1{#2}{#3#4}%
+   \fi}%
+}
+
+% Define @defun.
+
+% This is called to end the arguments processing for all the @def... commands.
+%
+\def\defargscommonending{%
+  \interlinepenalty = 10000
+  \advance\rightskip by 0pt plus 1fil
+  \endgraf
+  \nobreak\vskip -\parskip
+  \penalty 10002  % signal to \parsebodycommon and \defxbodycommon.
+}
+
+% This expands the args and terminates the paragraph they comprise.
+%
+\def\defunargs#1{\functionparens \sl
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Set the font temporarily and use \font in case \setfont made \tensl a macro.
+{\tensl\hyphenchar\font=0}%
+#1%
+{\tensl\hyphenchar\font=45}%
+\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi%
+  \defargscommonending
+}
+
+\def\deftypefunargs #1{%
+% Expand, preventing hyphenation at `-' chars.
+% Note that groups don't affect changes in \hyphenchar.
+% Use \boldbraxnoamp, not \functionparens, so that & is not special.
+\boldbraxnoamp
+\tclose{#1}% avoid \code because of side effects on active chars
+  \defargscommonending
+}
+
+% Do complete processing of one @defun or @defunx line already parsed.
+
+% @deffn Command forward-char nchars
+
+\def\deffn{\defmethparsebody\Edeffn\deffnx\deffnheader}
+
+\def\deffnheader #1#2#3{\doind {fn}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defunargs{#3}\endgroup %
+\catcode\equalChar=\other % Turn off change made in \defparsebody
+}
+
+% @defun == @deffn Function
+
+\def\defun{\defparsebody\Edefun\defunx\defunheader}
+
+\def\defunheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDeffunc}%
+\defunargs {#2}\endgroup %
+\catcode\equalChar=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefun int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefun{\defparsebody\Edeftypefun\deftypefunx\deftypefunheader}
+
+% #1 is the data type.  #2 is the name and args.
+\def\deftypefunheader #1#2{\deftypefunheaderx{#1}#2 \relax}
+% #1 is the data type, #2 the name, #3 the args.
+\def\deftypefunheaderx #1#2 #3\relax{%
+\doind {fn}{\code{#2}}% Make entry in function index
+\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypefun}%
+\deftypefunargs {#3}\endgroup %
+\catcode\equalChar=\other % Turn off change made in \defparsebody
+}
+
+% @deftypefn {Library Function} int foobar (int @var{foo}, float @var{bar})
+
+\def\deftypefn{\defmethparsebody\Edeftypefn\deftypefnx\deftypefnheader}
+
+% \defheaderxcond#1\relax$.$
+% puts #1 in @code, followed by a space, but does nothing if #1 is null.
+\def\defheaderxcond#1#2$.${\ifx#1\relax\else\code{#1#2} \fi}
+
+% #1 is the classification.  #2 is the data type.  #3 is the name and args.
+\def\deftypefnheader #1#2#3{\deftypefnheaderx{#1}{#2}#3 \relax}
+% #1 is the classification, #2 the data type, #3 the name, #4 the args.
+\def\deftypefnheaderx #1#2#3 #4\relax{%
+\doind {fn}{\code{#3}}% Make entry in function index
+\begingroup
+\normalparens % notably, turn off `&' magic, which prevents
+%               at least some C++ text from working
+\defname {\defheaderxcond#2\relax$.$#3}{#1}%
+\deftypefunargs {#4}\endgroup %
+\catcode\equalChar=\other % Turn off change made in \defparsebody
+}
+
+% @defmac == @deffn Macro
+
+\def\defmac{\defparsebody\Edefmac\defmacx\defmacheader}
+
+\def\defmacheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefmac}%
+\defunargs {#2}\endgroup %
+\catcode\equalChar=\other % Turn off change made in \defparsebody
+}
+
+% @defspec == @deffn Special Form
+
+\def\defspec{\defparsebody\Edefspec\defspecx\defspecheader}
+
+\def\defspecheader #1#2{\doind {fn}{\code{#1}}% Make entry in function index
+\begingroup\defname {#1}{\putwordDefspec}%
+\defunargs {#2}\endgroup %
+\catcode\equalChar=\other % Turn off change made in \defparsebody
+}
+
+% @defop CATEGORY CLASS OPERATION ARG...
+%
+\def\defop #1 {\def\defoptype{#1}%
+\defopparsebody\Edefop\defopx\defopheader\defoptype}
+%
+\def\defopheader#1#2#3{%
+  \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% function index entry
+  \begingroup
+    \defname{#2}{\defoptype\ \putwordon\ #1}%
+    \defunargs{#3}%
+  \endgroup
+}
+
+% @deftypeop CATEGORY CLASS TYPE OPERATION ARG...
+%
+\def\deftypeop #1 {\def\deftypeopcategory{#1}%
+  \deftypeopparsebody\Edeftypeop\deftypeopx\deftypeopheader
+                       \deftypeopcategory}
+%
+% #1 is the class name, #2 the data type, #3 the operation name, #4 the args.
+\def\deftypeopheader#1#2#3#4{%
+  \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+  \begingroup
+    \defname{\defheaderxcond#2\relax$.$#3}
+            {\deftypeopcategory\ \putwordon\ \code{#1}}%
+    \deftypefunargs{#4}%
+  \endgroup
+}
+
+% @deftypemethod CLASS TYPE METHOD ARG...
+%
+\def\deftypemethod{%
+  \deftypemethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader}
+%
+% #1 is the class name, #2 the data type, #3 the method name, #4 the args.
+\def\deftypemethodheader#1#2#3#4{%
+  \dosubind{fn}{\code{#3}}{\putwordon\ \code{#1}}% entry in function index
+  \begingroup
+    \defname{\defheaderxcond#2\relax$.$#3}{\putwordMethodon\ \code{#1}}%
+    \deftypefunargs{#4}%
+  \endgroup
+}
+
+% @deftypeivar CLASS TYPE VARNAME
+%
+\def\deftypeivar{%
+  \deftypemethparsebody\Edeftypeivar\deftypeivarx\deftypeivarheader}
+%
+% #1 is the class name, #2 the data type, #3 the variable name.
+\def\deftypeivarheader#1#2#3{%
+  \dosubind{vr}{\code{#3}}{\putwordof\ \code{#1}}% entry in variable index
+  \begingroup
+    \defname{\defheaderxcond#2\relax$.$#3}
+            {\putwordInstanceVariableof\ \code{#1}}%
+    \defvarargs{#3}%
+  \endgroup
+}
+
+% @defmethod == @defop Method
+%
+\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
+%
+% #1 is the class name, #2 the method name, #3 the args.
+\def\defmethodheader#1#2#3{%
+  \dosubind{fn}{\code{#2}}{\putwordon\ \code{#1}}% entry in function index
+  \begingroup
+    \defname{#2}{\putwordMethodon\ \code{#1}}%
+    \defunargs{#3}%
+  \endgroup
+}
+
+% @defcv {Class Option} foo-class foo-flag
+
+\def\defcv #1 {\def\defcvtype{#1}%
+\defopvarparsebody\Edefcv\defcvx\defcvarheader\defcvtype}
+
+\def\defcvarheader #1#2#3{%
+  \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% variable index entry
+  \begingroup
+    \defname{#2}{\defcvtype\ \putwordof\ #1}%
+    \defvarargs{#3}%
+  \endgroup
+}
+
+% @defivar CLASS VARNAME == @defcv {Instance Variable} CLASS VARNAME
+%
+\def\defivar{\defvrparsebody\Edefivar\defivarx\defivarheader}
+%
+\def\defivarheader#1#2#3{%
+  \dosubind{vr}{\code{#2}}{\putwordof\ \code{#1}}% entry in var index
+  \begingroup
+    \defname{#2}{\putwordInstanceVariableof\ #1}%
+    \defvarargs{#3}%
+  \endgroup
+}
+
+% @defvar
+% First, define the processing that is wanted for arguments of @defvar.
+% This is actually simple: just print them in roman.
+% This must expand the args and terminate the paragraph they make up
+\def\defvarargs #1{\normalparens #1%
+  \defargscommonending
+}
+
+% @defvr Counter foo-count
+
+\def\defvr{\defvrparsebody\Edefvr\defvrx\defvrheader}
+
+\def\defvrheader #1#2#3{\doind {vr}{\code{#2}}%
+\begingroup\defname {#2}{#1}\defvarargs{#3}\endgroup}
+
+% @defvar == @defvr Variable
+
+\def\defvar{\defvarparsebody\Edefvar\defvarx\defvarheader}
+
+\def\defvarheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefvar}%
+\defvarargs {#2}\endgroup %
+}
+
+% @defopt == @defvr {User Option}
+
+\def\defopt{\defvarparsebody\Edefopt\defoptx\defoptheader}
+
+\def\defoptheader #1#2{\doind {vr}{\code{#1}}% Make entry in var index
+\begingroup\defname {#1}{\putwordDefopt}%
+\defvarargs {#2}\endgroup %
+}
+
+% @deftypevar int foobar
+
+\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
+
+% #1 is the data type.  #2 is the name, perhaps followed by text that
+% is actually part of the data type, which should not be put into the index.
+\def\deftypevarheader #1#2{%
+\dovarind#2 \relax% Make entry in variables index
+\begingroup\defname {\defheaderxcond#1\relax$.$#2}{\putwordDeftypevar}%
+  \defargscommonending
+\endgroup}
+\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}}
+
+% @deftypevr {Global Flag} int enable
+
+\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
+
+\def\deftypevrheader #1#2#3{\dovarind#3 \relax%
+\begingroup\defname {\defheaderxcond#2\relax$.$#3}{#1}
+  \defargscommonending
+\endgroup}
+
+% Now define @deftp
+% Args are printed in bold, a slight difference from @defvar.
+
+\def\deftpargs #1{\bf \defvarargs{#1}}
+
+% @deftp Class window height width ...
+
+\def\deftp{\deftpparsebody\Edeftp\deftpx\deftpheader}
+
+\def\deftpheader #1#2#3{\doind {tp}{\code{#2}}%
+\begingroup\defname {#2}{#1}\deftpargs{#3}\endgroup}
+
+% These definitions are used if you use @defunx (etc.)
+% anywhere other than immediately after a @defun or @defunx.
+%
+\def\defcvx#1 {\errmessage{@defcvx in invalid context}}
+\def\deffnx#1 {\errmessage{@deffnx in invalid context}}
+\def\defivarx#1 {\errmessage{@defivarx in invalid context}}
+\def\defmacx#1 {\errmessage{@defmacx in invalid context}}
+\def\defmethodx#1 {\errmessage{@defmethodx in invalid context}}
+\def\defoptx #1 {\errmessage{@defoptx in invalid context}}
+\def\defopx#1 {\errmessage{@defopx in invalid context}}
+\def\defspecx#1 {\errmessage{@defspecx in invalid context}}
+\def\deftpx#1 {\errmessage{@deftpx in invalid context}}
+\def\deftypefnx#1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypefunx#1 {\errmessage{@deftypefunx in invalid context}}
+\def\deftypeivarx#1 {\errmessage{@deftypeivarx in invalid context}}
+\def\deftypemethodx#1 {\errmessage{@deftypemethodx in invalid context}}
+\def\deftypeopx#1 {\errmessage{@deftypeopx in invalid context}}
+\def\deftypevarx#1 {\errmessage{@deftypevarx in invalid context}}
+\def\deftypevrx#1 {\errmessage{@deftypevrx in invalid context}}
+\def\defunx#1 {\errmessage{@defunx in invalid context}}
+\def\defvarx#1 {\errmessage{@defvarx in invalid context}}
+\def\defvrx#1 {\errmessage{@defvrx in invalid context}}
+
+
+\message{macros,}
+% @macro.
+
+% To do this right we need a feature of e-TeX, \scantokens,
+% which we arrange to emulate with a temporary file in ordinary TeX.
+\ifx\eTeXversion\undefined
+ \newwrite\macscribble
+ \def\scanmacro#1{%
+   \begingroup \newlinechar`\^^M
+   % Undo catcode changes of \startcontents and \doprintindex
+   \catcode`\@=0 \catcode`\\=\other \escapechar=`\@
+   % Append \endinput to make sure that TeX does not see the ending newline.
+   \toks0={#1\endinput}%
+   \immediate\openout\macscribble=\jobname.tmp
+   \immediate\write\macscribble{\the\toks0}%
+   \immediate\closeout\macscribble
+   \let\xeatspaces\eatspaces
+   \input \jobname.tmp
+   \endgroup
+}
+\else
+\def\scanmacro#1{%
+\begingroup \newlinechar`\^^M
+% Undo catcode changes of \startcontents and \doprintindex
+\catcode`\@=0 \catcode`\\=\other \escapechar=`\@
+\let\xeatspaces\eatspaces\scantokens{#1\endinput}\endgroup}
+\fi
+
+\newcount\paramno   % Count of parameters
+\newtoks\macname    % Macro name
+\newif\ifrecursive  % Is it recursive?
+\def\macrolist{}    % List of all defined macros in the form
+                    % \do\macro1\do\macro2...
+
+% Utility routines.
+% Thisdoes \let #1 = #2, except with \csnames.
+\def\cslet#1#2{%
+\expandafter\expandafter
+\expandafter\let
+\expandafter\expandafter
+\csname#1\endcsname
+\csname#2\endcsname}
+
+% Trim leading and trailing spaces off a string.
+% Concepts from aro-bend problem 15 (see CTAN).
+{\catcode`\@=11
+\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
+\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
+\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
+\def\unbrace#1{#1}
+\unbrace{\gdef\trim@@@ #1 } #2@{#1}
+}
+
+% Trim a single trailing ^^M off a string.
+{\catcode`\^^M=\other \catcode`\Q=3%
+\gdef\eatcr #1{\eatcra #1Q^^MQ}%
+\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
+\gdef\eatcrb#1Q#2Q{#1}%
+}
+
+% Macro bodies are absorbed as an argument in a context where
+% all characters are catcode 10, 11 or 12, except \ which is active
+% (as in normal texinfo). It is necessary to change the definition of \.
+
+% It's necessary to have hard CRs when the macro is executed. This is
+% done by  making ^^M (\endlinechar) catcode 12 when reading the macro
+% body, and then making it the \newlinechar in \scanmacro.
+
+\def\macrobodyctxt{%
+  \catcode`\~=\other
+  \catcode`\^=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\+=\other
+  \catcode`\{=\other
+  \catcode`\}=\other
+  \catcode`\@=\other
+  \catcode`\^^M=\other
+  \usembodybackslash}
+
+\def\macroargctxt{%
+  \catcode`\~=\other
+  \catcode`\^=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\+=\other
+  \catcode`\@=\other
+  \catcode`\\=\other}
+
+% \mbodybackslash is the definition of \ in @macro bodies.
+% It maps \foo\ => \csname macarg.foo\endcsname => #N
+% where N is the macro parameter number.
+% We define \csname macarg.\endcsname to be \realbackslash, so
+% \\ in macro replacement text gets you a backslash.
+
+{\catcode`@=0 @catcode`@\=@active
+ @gdef@usembodybackslash{@let\=@mbodybackslash}
+ @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
+}
+\expandafter\def\csname macarg.\endcsname{\realbackslash}
+
+\def\macro{\recursivefalse\parsearg\macroxxx}
+\def\rmacro{\recursivetrue\parsearg\macroxxx}
+
+\def\macroxxx#1{%
+  \getargs{#1}%           now \macname is the macname and \argl the arglist
+  \ifx\argl\empty       % no arguments
+     \paramno=0%
+  \else
+     \expandafter\parsemargdef \argl;%
+  \fi
+  \if1\csname ismacro.\the\macname\endcsname
+     \message{Warning: redefining \the\macname}%
+  \else
+     \expandafter\ifx\csname \the\macname\endcsname \relax
+     \else \errmessage{Macro name \the\macname\space already defined}\fi
+     \global\cslet{macsave.\the\macname}{\the\macname}%
+     \global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
+     % Add the macroname to \macrolist
+     \toks0 = \expandafter{\macrolist\do}%
+     \xdef\macrolist{\the\toks0
+       \expandafter\noexpand\csname\the\macname\endcsname}%
+  \fi
+  \begingroup \macrobodyctxt
+  \ifrecursive \expandafter\parsermacbody
+  \else \expandafter\parsemacbody
+  \fi}
+
+\def\unmacro{\parsearg\dounmacro}
+\def\dounmacro#1{%
+  \if1\csname ismacro.#1\endcsname
+    \global\cslet{#1}{macsave.#1}%
+    \global\expandafter\let \csname ismacro.#1\endcsname=0%
+    % Remove the macro name from \macrolist:
+    \begingroup
+      \expandafter\let\csname#1\endcsname \relax
+      \let\do\unmacrodo
+      \xdef\macrolist{\macrolist}%
+    \endgroup
+  \else
+    \errmessage{Macro #1 not defined}%
+  \fi
+}
+
+% Called by \do from \dounmacro on each macro.  The idea is to omit any
+% macro definitions that have been changed to \relax.
+%
+\def\unmacrodo#1{%
+  \ifx#1\relax
+    % remove this
+  \else
+    \noexpand\do \noexpand #1%
+  \fi
+}
+
+% This makes use of the obscure feature that if the last token of a
+% <parameter list> is #, then the preceding argument is delimited by
+% an opening brace, and that opening brace is not consumed.
+\def\getargs#1{\getargsxxx#1{}}
+\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
+\def\getmacname #1 #2\relax{\macname={#1}}
+\def\getmacargs#1{\def\argl{#1}}
+
+% Parse the optional {params} list.  Set up \paramno and \paramlist
+% so \defmacro knows what to do.  Define \macarg.blah for each blah
+% in the params list, to be ##N where N is the position in that list.
+% That gets used by \mbodybackslash (above).
+
+% We need to get `macro parameter char #' into several definitions.
+% The technique used is stolen from LaTeX:  let \hash be something
+% unexpandable, insert that wherever you need a #, and then redefine
+% it to # just before using the token list produced.
+%
+% The same technique is used to protect \eatspaces till just before
+% the macro is used.
+
+\def\parsemargdef#1;{\paramno=0\def\paramlist{}%
+        \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,}
+\def\parsemargdefxxx#1,{%
+  \if#1;\let\next=\relax
+  \else \let\next=\parsemargdefxxx
+    \advance\paramno by 1%
+    \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
+        {\xeatspaces{\hash\the\paramno}}%
+    \edef\paramlist{\paramlist\hash\the\paramno,}%
+  \fi\next}
+
+% These two commands read recursive and nonrecursive macro bodies.
+% (They're different since rec and nonrec macros end differently.)
+
+\long\def\parsemacbody#1@end macro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+\long\def\parsermacbody#1@end rmacro%
+{\xdef\temp{\eatcr{#1}}\endgroup\defmacro}%
+
+% This defines the macro itself. There are six cases: recursive and
+% nonrecursive macros of zero, one, and many arguments.
+% Much magic with \expandafter here.
+% \xdef is used so that macro definitions will survive the file
+% they're defined in; @include reads the file inside a group.
+\def\defmacro{%
+  \let\hash=##% convert placeholders to macro parameter chars
+  \ifrecursive
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\scanmacro{\temp}}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+         \egroup\noexpand\scanmacro{\temp}}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+        \csname\the\macname xxx\endcsname
+          \paramlist{\egroup\noexpand\scanmacro{\temp}}%
+    \fi
+  \else
+    \ifcase\paramno
+    % 0
+      \expandafter\xdef\csname\the\macname\endcsname{%
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \or % 1
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \noexpand\braceorline
+         \expandafter\noexpand\csname\the\macname xxx\endcsname}%
+      \expandafter\xdef\csname\the\macname xxx\endcsname##1{%
+        \egroup
+        \noexpand\norecurse{\the\macname}%
+        \noexpand\scanmacro{\temp}\egroup}%
+    \else % many
+      \expandafter\xdef\csname\the\macname\endcsname{%
+         \bgroup\noexpand\macroargctxt
+         \expandafter\noexpand\csname\the\macname xx\endcsname}%
+      \expandafter\xdef\csname\the\macname xx\endcsname##1{%
+          \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}%
+      \expandafter\expandafter
+      \expandafter\xdef
+      \expandafter\expandafter
+      \csname\the\macname xxx\endcsname
+      \paramlist{%
+          \egroup
+          \noexpand\norecurse{\the\macname}%
+          \noexpand\scanmacro{\temp}\egroup}%
+    \fi
+  \fi}
+
+\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+% \braceorline decides whether the next nonwhitespace character is a
+% {.  If so it reads up to the closing }, if not, it reads the whole
+% line.  Whatever was read is then fed to the next control sequence
+% as an argument (by \parsebrace or \parsearg)
+\def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx}
+\def\braceorlinexxx{%
+  \ifx\nchar\bgroup\else
+    \expandafter\parsearg
+  \fi \next}
+
+% We mant to disable all macros during \shipout so that they are not
+% expanded by \write.
+\def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}%
+  \edef\next{\macrolist}\expandafter\endgroup\next}
+
+
+% @alias.
+% We need some trickery to remove the optional spaces around the equal
+% sign.  Just make them active and then expand them all to nothing.
+\def\alias{\begingroup\obeyspaces\parsearg\aliasxxx}
+\def\aliasxxx #1{\aliasyyy#1\relax}
+\def\aliasyyy #1=#2\relax{\ignoreactivespaces
+\edef\next{\global\let\expandafter\noexpand\csname#1\endcsname=%
+           \expandafter\noexpand\csname#2\endcsname}%
+\expandafter\endgroup\next}
+
+
+\message{cross references,}
+
+\newwrite\auxfile
+
+\newif\ifhavexrefs    % True if xref values are known.
+\newif\ifwarnedxrefs  % True if we warned once that they aren't known.
+
+% @inforef is relatively simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+  node \samp{\ignorespaces#1{}}}
+
+% @node's only job in TeX is to define \lastnode, which is used in
+% cross-references.
+\def\node{\ENVcheck\parsearg\nodezzz}
+\def\nodezzz#1{\nodexxx #1,\finishnodeparse}
+\def\nodexxx#1,#2\finishnodeparse{\gdef\lastnode{#1}}
+\let\nwnode=\node
+\let\lastnode=\empty
+
+% Write a cross-reference definition for the current node.  #1 is the
+% type (Ynumbered, Yappendix, Ynothing).
+% 
+\def\donoderef#1{%
+  \ifx\lastnode\empty\else
+    \setref{\lastnode}{#1}%
+    \global\let\lastnode=\empty
+  \fi
+}
+
+% @anchor{NAME} -- define xref target at arbitrary point.
+%
+\newcount\savesfregister
+%
+\gdef\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
+\gdef\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
+\gdef\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
+
+% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
+% anchor), namely NAME-title (the corresponding @chapter/etc. name),
+% NAME-pg (the page number), and NAME-snt (section number and type).
+% Called from \foonoderef.
+% 
+% We take care not to expand the title.
+%
+% Use \turnoffactive so that punctuation chars such as underscore
+% and backslash work in node names.
+%
+\def\setref#1#2{%
+  \pdfmkdest{#1}%
+  \iflinks
+    {%
+      \turnoffactive
+      \edef\writexrdef##1##2{%
+       \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
+         ##1}{##2}}% these are parameters of \writexrdef
+      }
+      \toks0 = \expandafter{\thissection}
+      \immediate \writexrdef{title}{\the\toks0 }%
+      \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
+      \writexrdef{pg}{\folio}% will be written later, during \shipout
+    }%
+  \fi
+}
+
+% @xref, @pxref, and @ref generate cross-references.  For \xrefX, #1 is
+% the node name, #2 the name of the Info cross-reference, #3 the printed
+% node name, #4 the name of the Info file, #5 the name of the printed
+% manual.  All but the node name can be omitted.
+%
+\def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]}
+\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
+\def\ref#1{\xrefX[#1,,,,,,,]}
+\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
+  \unsepspaces
+  \def\printedmanual{\ignorespaces #5}%
+  \def\printednodename{\ignorespaces #3}%
+  \setbox1=\hbox{\printedmanual}%
+  \setbox0=\hbox{\printednodename}%
+  \ifdim \wd0 = 0pt
+    % No printed node name was explicitly given.
+    \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
+      % Use the node name inside the square brackets.
+      \def\printednodename{\ignorespaces #1}%
+    \else
+      % Use the actual chapter/section title appear inside
+      % the square brackets.  Use the real section title if we have it.
+      \ifdim \wd1 > 0pt
+        % It is in another manual, so we don't have it.
+        \def\printednodename{\ignorespaces #1}%
+      \else
+        \ifhavexrefs
+          % We know the real title if we have the xref values.
+          \def\printednodename{\refx{#1-title}{}}%
+        \else
+          % Otherwise just copy the Info node name.
+          \def\printednodename{\ignorespaces #1}%
+        \fi%
+      \fi
+    \fi
+  \fi
+  %
+  % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not
+  % insert empty discretionaries after hyphens, which means that it will
+  % not find a line break at a hyphen in a node names.  Since some manuals
+  % are best written with fairly long node names, containing hyphens, this
+  % is a loss.  Therefore, we give the text of the node name again, so it
+  % is as if TeX is seeing it for the first time.
+  \ifpdf
+    \leavevmode
+    \getfilename{#4}%
+    {\turnoffactive \otherbackslash
+     \ifnum\filenamelength>0
+       \startlink attr{/Border [0 0 0]}%
+         goto file{\the\filename.pdf} name{#1}%
+     \else
+       \startlink attr{/Border [0 0 0]}%
+         goto name{\pdfmkpgn{#1}}%
+     \fi
+    }%
+    \linkcolor
+  \fi
+  %
+  \ifdim \wd1 > 0pt
+    \putwordsection{} ``\printednodename'' \putwordin{} \cite{\printedmanual}%
+  \else
+    % _ (for example) has to be the character _ for the purposes of the
+    % control sequence corresponding to the node, but it has to expand
+    % into the usual \leavevmode...\vrule stuff for purposes of
+    % printing. So we \turnoffactive for the \refx-snt, back on for the
+    % printing, back off for the \refx-pg.
+    {\turnoffactive \otherbackslash
+     % Only output a following space if the -snt ref is nonempty; for
+     % @unnumbered and @anchor, it won't be.
+     \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}%
+     \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
+    }%
+    % output the `[mynode]' via a macro.
+    \xrefprintnodename\printednodename
+    %
+    % But we always want a comma and a space:
+    ,\space
+    %
+    % output the `page 3'.
+    \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}%
+  \fi
+  \endlink
+\endgroup}
+
+% This macro is called from \xrefX for the `[nodename]' part of xref
+% output.  It's a separate macro only so it can be changed more easily,
+% since not square brackets don't work in some documents.  Particularly
+% one that Bob is working on :).
+%
+\def\xrefprintnodename#1{[#1]}
+
+% Things referred to by \setref.
+%
+\def\Ynothing{}
+\def\Yomitfromtoc{}
+\def\Ynumbered{%
+  \ifnum\secno=0
+    \putwordChapter@tie \the\chapno
+  \else \ifnum\subsecno=0
+    \putwordSection@tie \the\chapno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+\def\Yappendix{%
+  \ifnum\secno=0
+     \putwordAppendix@tie @char\the\appendixno{}%
+  \else \ifnum\subsecno=0
+     \putwordSection@tie @char\the\appendixno.\the\secno
+  \else \ifnum\subsubsecno=0
+    \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno
+  \else
+    \putwordSection@tie
+      @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno
+  \fi\fi\fi
+}
+
+% Use TeX 3.0's \inputlineno to get the line number, for better error
+% messages, but if we're using an old version of TeX, don't do anything.
+%
+\ifx\inputlineno\thisisundefined
+  \let\linenumber = \empty % Pre-3.0.
+\else
+  \def\linenumber{\the\inputlineno:\space}
+\fi
+
+% Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME.
+% If its value is nonempty, SUFFIX is output afterward.
+%
+\def\refx#1#2{%
+  {%
+    \indexnofonts
+    \otherbackslash
+    \expandafter\global\expandafter\let\expandafter\thisrefX
+      \csname X#1\endcsname
+  }%
+  \ifx\thisrefX\relax
+    % If not defined, say something at least.
+    \angleleft un\-de\-fined\angleright
+    \iflinks
+      \ifhavexrefs
+        \message{\linenumber Undefined cross reference `#1'.}%
+      \else
+        \ifwarnedxrefs\else
+          \global\warnedxrefstrue
+          \message{Cross reference values unknown; you must run TeX again.}%
+        \fi
+      \fi
+    \fi
+  \else
+    % It's defined, so just use it.
+    \thisrefX
+  \fi
+  #2% Output the suffix in any case.
+}
+
+% This is the macro invoked by entries in the aux file.
+%
+\def\xrdef#1{\expandafter\gdef\csname X#1\endcsname}
+
+% Read the last existing aux file, if any.  No error if none exists.
+\def\readauxfile{\begingroup
+  \catcode`\^^@=\other
+  \catcode`\^^A=\other
+  \catcode`\^^B=\other
+  \catcode`\^^C=\other
+  \catcode`\^^D=\other
+  \catcode`\^^E=\other
+  \catcode`\^^F=\other
+  \catcode`\^^G=\other
+  \catcode`\^^H=\other
+  \catcode`\^^K=\other
+  \catcode`\^^L=\other
+  \catcode`\^^N=\other
+  \catcode`\^^P=\other
+  \catcode`\^^Q=\other
+  \catcode`\^^R=\other
+  \catcode`\^^S=\other
+  \catcode`\^^T=\other
+  \catcode`\^^U=\other
+  \catcode`\^^V=\other
+  \catcode`\^^W=\other
+  \catcode`\^^X=\other
+  \catcode`\^^Z=\other
+  \catcode`\^^[=\other
+  \catcode`\^^\=\other
+  \catcode`\^^]=\other
+  \catcode`\^^^=\other
+  \catcode`\^^_=\other
+  % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc.
+  % in xref tags, i.e., node names.  But since ^^e4 notation isn't
+  % supported in the main text, it doesn't seem desirable.  Furthermore,
+  % that is not enough: for node names that actually contain a ^
+  % character, we would end up writing a line like this: 'xrdef {'hat
+  % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+  % argument, and \hat is not an expandable control sequence.  It could
+  % all be worked out, but why?  Either we support ^^ or we don't.
+  %
+  % The other change necessary for this was to define \auxhat:
+  % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+  % and then to call \auxhat in \setq.
+  %
+  \catcode`\^=\other
+  %
+  % Special characters.  Should be turned off anyway, but...
+  \catcode`\~=\other
+  \catcode`\[=\other
+  \catcode`\]=\other
+  \catcode`\"=\other
+  \catcode`\_=\other
+  \catcode`\|=\other
+  \catcode`\<=\other
+  \catcode`\>=\other
+  \catcode`\$=\other
+  \catcode`\#=\other
+  \catcode`\&=\other
+  \catcode`\%=\other
+  \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
+  %
+  % Make the characters 128-255 be printing characters
+  {%
+    \count 1=128
+    \def\loop{%
+      \catcode\count 1=\other
+      \advance\count 1 by 1
+      \ifnum \count 1<256 \loop \fi
+    }%
+  }%
+  %
+  % Turn off \ as an escape so we do not lose on
+  % entries which were dumped with control sequences in their names.
+  % For example, @xrdef{$\leq $-fun}{page ...} made by @defun ^^
+  % Reference to such entries still does not work the way one would wish,
+  % but at least they do not bomb out when the aux file is read in.
+  \catcode`\\=\other
+  %
+  % @ is our escape character in .aux files.
+  \catcode`\{=1
+  \catcode`\}=2
+  \catcode`\@=0
+  %
+  \openin 1 \jobname.aux
+  \ifeof 1 \else
+    \closein 1
+    \input \jobname.aux
+    \global\havexrefstrue
+  \fi
+  % Open the new aux file.  TeX will close it automatically at exit.
+  \openout\auxfile=\jobname.aux
+\endgroup}
+
+
+% Footnotes.
+
+\newcount \footnoteno
+
+% The trailing space in the following definition for supereject is
+% vital for proper filling; pages come out unaligned when you do a
+% pagealignmacro call if that space before the closing brace is
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
+\def\supereject{\par\penalty -20000\footnoteno =0 }
+
+% @footnotestyle is meaningful for info output only.
+\let\footnotestyle=\comment
+
+\let\ptexfootnote=\footnote
+
+{\catcode `\@=11
+%
+% Auto-number footnotes.  Otherwise like plain.
+\gdef\footnote{%
+  \let\indent=\ptexindent
+  \let\noindent=\ptexnoindent
+  \global\advance\footnoteno by \@ne
+  \edef\thisfootno{$^{\the\footnoteno}$}%
+  %
+  % In case the footnote comes at the end of a sentence, preserve the
+  % extra spacing after we do the footnote number.
+  \let\@sf\empty
+  \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
+  %
+  % Remove inadvertent blank space before typesetting the footnote number.
+  \unskip
+  \thisfootno\@sf
+  \dofootnote
+}%
+
+% Don't bother with the trickery in plain.tex to not require the
+% footnote text as a parameter.  Our footnotes don't need to be so general.
+%
+% Oh yes, they do; otherwise, @ifset and anything else that uses
+% \parseargline fail inside footnotes because the tokens are fixed when
+% the footnote is read.  --karl, 16nov96.
+%
+% The start of the footnote looks usually like this:
+\gdef\startfootins{\insert\footins\bgroup}
+%
+% ... but this macro is redefined inside @multitable.
+%
+\gdef\dofootnote{%
+  \startfootins
+  % We want to typeset this text as a normal paragraph, even if the
+  % footnote reference occurs in (for example) a display environment.
+  % So reset some parameters.
+  \hsize=\pagewidth
+  \interlinepenalty\interfootnotelinepenalty
+  \splittopskip\ht\strutbox % top baseline for broken footnotes
+  \splitmaxdepth\dp\strutbox
+  \floatingpenalty\@MM
+  \leftskip\z@skip
+  \rightskip\z@skip
+  \spaceskip\z@skip
+  \xspaceskip\z@skip
+  \parindent\defaultparindent
+  %
+  \smallfonts \rm
+  %
+  % Because we use hanging indentation in footnotes, a @noindent appears
+  % to exdent this text, so make it be a no-op.  makeinfo does not use
+  % hanging indentation so @noindent can still be needed within footnote
+  % text after an @example or the like (not that this is good style).
+  \let\noindent = \relax
+  %
+  % Hang the footnote text off the number.  Use \everypar in case the
+  % footnote extends for more than one paragraph.
+  \everypar = {\hang}%
+  \textindent{\thisfootno}%
+  %
+  % Don't crash into the line above the footnote text.  Since this
+  % expands into a box, it must come within the paragraph, lest it
+  % provide a place where TeX can split the footnote.
+  \footstrut
+  \futurelet\next\fo@t
+}
+}%end \catcode `\@=11
+
+% @| inserts a changebar to the left of the current line.  It should
+% surround any changed text.  This approach does *not* work if the
+% change spans more than two lines of output.  To handle that, we would
+% have adopt a much more difficult approach (putting marks into the main
+% vertical list for the beginning and end of each change).
+%
+\def\|{%
+  % \vadjust can only be used in horizontal mode.
+  \leavevmode
+  %
+  % Append this vertical mode material after the current line in the output.
+  \vadjust{%
+    % We want to insert a rule with the height and depth of the current
+    % leading; that is exactly what \strutbox is supposed to record.
+    \vskip-\baselineskip
+    %
+    % \vadjust-items are inserted at the left edge of the type.  So
+    % the \llap here moves out into the left-hand margin.
+    \llap{%
+      %
+      % For a thicker or thinner bar, change the `1pt'.
+      \vrule height\baselineskip width1pt
+      %
+      % This is the space between the bar and the text.
+      \hskip 12pt
+    }%
+  }%
+}
+
+% For a final copy, take out the rectangles
+% that mark overfull boxes (in case you have decided
+% that the text looks ok even though it passes the margin).
+%
+\def\finalout{\overfullrule=0pt}
+
+% @image.  We use the macros from epsf.tex to support this.
+% If epsf.tex is not installed and @image is used, we complain.
+%
+% Check for and read epsf.tex up front.  If we read it only at @image
+% time, we might be inside a group, and then its definitions would get
+% undone and the next image would fail.
+\openin 1 = epsf.tex
+\ifeof 1 \else
+  \closein 1
+  % Do not bother showing banner with epsf.tex v2.7k (available in
+  % doc/epsf.tex and on ctan).
+  \def\epsfannounce{\toks0 = }%
+  \input epsf.tex
+\fi
+%
+% We will only complain once about lack of epsf.tex.
+\newif\ifwarnednoepsf
+\newhelp\noepsfhelp{epsf.tex must be installed for images to
+  work.  It is also included in the Texinfo distribution, or you can get
+  it from ftp://tug.org/tex/epsf.tex.}
+%
+\def\image#1{%
+  \ifx\epsfbox\undefined
+    \ifwarnednoepsf \else
+      \errhelp = \noepsfhelp
+      \errmessage{epsf.tex not found, images will be ignored}%
+      \global\warnednoepsftrue
+    \fi
+  \else
+    \imagexxx #1,,,,,\finish
+  \fi
+}
+%
+% Arguments to @image:
+% #1 is (mandatory) image filename; we tack on .eps extension.
+% #2 is (optional) width, #3 is (optional) height.
+% #4 is (ignored optional) html alt text.
+% #5 is (ignored optional) extension.
+% #6 is just the usual extra ignored arg for parsing this stuff.
+\newif\ifimagevmode
+\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
+  \catcode`\^^M = 5     % in case we're inside an example
+  \normalturnoffactive  % allow _ et al. in names
+  % If the image is by itself, center it.
+  \ifvmode
+    \imagevmodetrue
+    \nobreak\bigskip
+    % Usually we'll have text after the image which will insert
+    % \parskip glue, so insert it here too to equalize the space
+    % above and below.
+    \nobreak\vskip\parskip
+    \nobreak
+    \line\bgroup\hss
+  \fi
+  %
+  % Output the image.
+  \ifpdf
+    \dopdfimage{#1}{#2}{#3}%
+  \else
+    % \epsfbox itself resets \epsf?size at each figure.
+    \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+    \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+    \epsfbox{#1.eps}%
+  \fi
+  %
+  \ifimagevmode \hss \egroup \bigbreak \fi  % space after the image
+\endgroup}
+
+
+\message{localization,}
+% and i18n.
+
+% @documentlanguage is usually given very early, just after
+% @setfilename.  If done too late, it may not override everything
+% properly.  Single argument is the language abbreviation.
+% It would be nice if we could set up a hyphenation file here.
+%
+\def\documentlanguage{\parsearg\dodocumentlanguage}
+\def\dodocumentlanguage#1{%
+  \tex % read txi-??.tex file in plain TeX.
+  % Read the file if it exists.
+  \openin 1 txi-#1.tex
+  \ifeof1
+    \errhelp = \nolanghelp
+    \errmessage{Cannot read language file txi-#1.tex}%
+    \let\temp = \relax
+  \else
+    \def\temp{\input txi-#1.tex }%
+  \fi
+  \temp
+  \endgroup
+}
+\newhelp\nolanghelp{The given language definition file cannot be found or
+is empty.  Maybe you need to install it?  In the current directory
+should work if nowhere else does.}
+
+
+% @documentencoding should change something in TeX eventually, most
+% likely, but for now just recognize it.
+\let\documentencoding = \comment
+
+
+% Page size parameters.
+%
+\newdimen\defaultparindent \defaultparindent = 15pt
+
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
+% Prevent underfull vbox error messages.
+\vbadness = 10000
+
+% Don't be so finicky about underfull hboxes, either.
+\hbadness = 2000
+
+% Following George Bush, just get rid of widows and orphans.
+\widowpenalty=10000
+\clubpenalty=10000
+
+% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
+% using an old version of TeX, don't do anything.  We want the amount of
+% stretch added to depend on the line length, hence the dependence on
+% \hsize.  We call this whenever the paper size is set.
+%
+\def\setemergencystretch{%
+  \ifx\emergencystretch\thisisundefined
+    % Allow us to assign to \emergencystretch anyway.
+    \def\emergencystretch{\dimen0}%
+  \else
+    \emergencystretch = .15\hsize
+  \fi
+}
+
+% Parameters in order: 1) textheight; 2) textwidth; 3) voffset;
+% 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8)
+% physical page width.
+%
+% We also call \setleading{\textleading}, so the caller should define
+% \textleading.  The caller should also set \parskip.
+%
+\def\internalpagesizes#1#2#3#4#5#6#7#8{%
+  \voffset = #3\relax
+  \topskip = #6\relax
+  \splittopskip = \topskip
+  %
+  \vsize = #1\relax
+  \advance\vsize by \topskip
+  \outervsize = \vsize
+  \advance\outervsize by 2\topandbottommargin
+  \pageheight = \vsize
+  %
+  \hsize = #2\relax
+  \outerhsize = \hsize
+  \advance\outerhsize by 0.5in
+  \pagewidth = \hsize
+  %
+  \normaloffset = #4\relax
+  \bindingoffset = #5\relax
+  %
+  \ifpdf
+    \pdfpageheight #7\relax
+    \pdfpagewidth #8\relax
+  \fi
+  %
+  \setleading{\textleading}
+  %
+  \parindent = \defaultparindent
+  \setemergencystretch
+}
+
+% @letterpaper (the default).
+\def\letterpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % If page is nothing but text, make it come out even.
+  \internalpagesizes{46\baselineskip}{6in}%
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{36pt}%
+                    {11in}{8.5in}%
+}}
+
+% Use @smallbook to reset parameters for 7x9.5 (or so) format.
+\def\smallbook{{\globaldefs = 1
+  \parskip = 2pt plus 1pt
+  \textleading = 12pt
+  %
+  \internalpagesizes{7.5in}{5in}%
+                    {\voffset}{.25in}%
+                    {\bindingoffset}{16pt}%
+                    {9.25in}{7in}%
+  %
+  \lispnarrowing = 0.3in
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = .5cm
+}}
+
+% Use @afourpaper to print on European A4 paper.
+\def\afourpaper{{\globaldefs = 1
+  \parskip = 3pt plus 2pt minus 1pt
+  \textleading = 13.2pt
+  %
+  % Double-side printing via postscript on Laserjet 4050
+  % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
+  % To change the settings for a different printer or situation, adjust
+  % \normaloffset until the front-side and back-side texts align.  Then
+  % do the same for \bindingoffset.  You can set these for testing in
+  % your texinfo source file like this:
+  % @tex
+  % \global\normaloffset = -6mm
+  % \global\bindingoffset = 10mm
+  % @end tex
+  \internalpagesizes{51\baselineskip}{160mm}
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{44pt}%
+                    {297mm}{210mm}%
+  %
+  \tolerance = 700
+  \hfuzz = 1pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 5mm
+}}
+
+% Use @afivepaper to print on European A5 paper.
+% From romildo@urano.iceb.ufop.br, 2 July 2000.
+% He also recommends making @example and @lisp be small.
+\def\afivepaper{{\globaldefs = 1
+  \parskip = 2pt plus 1pt minus 0.1pt
+  \textleading = 12.5pt
+  %
+  \internalpagesizes{160mm}{120mm}%
+                    {\voffset}{\hoffset}%
+                    {\bindingoffset}{8pt}%
+                    {210mm}{148mm}%
+  %
+  \lispnarrowing = 0.2in
+  \tolerance = 800
+  \hfuzz = 1.2pt
+  \contentsrightmargin = 0pt
+  \defbodyindent = 2mm
+  \tableindent = 12mm
+}}
+
+% A specific text layout, 24x15cm overall, intended for A4 paper.
+\def\afourlatex{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{237mm}{150mm}%
+                    {\voffset}{4.6mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  %
+  % Must explicitly reset to 0 because we call \afourpaper.
+  \globaldefs = 0
+}}
+
+% Use @afourwide to print on A4 paper in landscape format.
+\def\afourwide{{\globaldefs = 1
+  \afourpaper
+  \internalpagesizes{241mm}{165mm}%
+                    {\voffset}{-2.95mm}%
+                    {\bindingoffset}{7mm}%
+                    {297mm}{210mm}%
+  \globaldefs = 0
+}}
+
+% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
+% Perhaps we should allow setting the margins, \topskip, \parskip,
+% and/or leading, also. Or perhaps we should compute them somehow.
+%
+\def\pagesizes{\parsearg\pagesizesxxx}
+\def\pagesizesxxx#1{\pagesizesyyy #1,,\finish}
+\def\pagesizesyyy#1,#2,#3\finish{{%
+  \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
+  \globaldefs = 1
+  %
+  \parskip = 3pt plus 2pt minus 1pt
+  \setleading{\textleading}%
+  %
+  \dimen0 = #1
+  \advance\dimen0 by \voffset
+  %
+  \dimen2 = \hsize
+  \advance\dimen2 by \normaloffset
+  %
+  \internalpagesizes{#1}{\hsize}%
+                    {\voffset}{\normaloffset}%
+                    {\bindingoffset}{44pt}%
+                    {\dimen0}{\dimen2}%
+}}
+
+% Set default to letter.
+%
+\letterpaper
+
+
+\message{and turning on texinfo input format.}
+
+% Define macros to output various characters with catcode for normal text.
+\catcode`\"=\other
+\catcode`\~=\other
+\catcode`\^=\other
+\catcode`\_=\other
+\catcode`\|=\other
+\catcode`\<=\other
+\catcode`\>=\other
+\catcode`\+=\other
+\catcode`\$=\other
+\def\normaldoublequote{"}
+\def\normaltilde{~}
+\def\normalcaret{^}
+\def\normalunderscore{_}
+\def\normalverticalbar{|}
+\def\normalless{<}
+\def\normalgreater{>}
+\def\normalplus{+}
+\def\normaldollar{$}%$ font-lock fix
+
+% This macro is used to make a character print one way in ttfont
+% where it can probably just be output, and another way in other fonts,
+% where something hairier probably needs to be done.
+%
+% #1 is what to print if we are indeed using \tt; #2 is what to print
+% otherwise.  Since all the Computer Modern typewriter fonts have zero
+% interword stretch (and shrink), and it is reasonable to expect all
+% typewriter fonts to have this, we can check that font parameter.
+%
+\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
+
+% Same as above, but check for italic font.  Actually this also catches
+% non-italic slanted fonts since it is impossible to distinguish them from
+% italic fonts.  But since this is only used by $ and it uses \sl anyway
+% this is not a problem.
+\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
+
+% Turn off all special characters except @
+% (and those which the user can use as if they were ordinary).
+% Most of these we simply print from the \tt font, but for some, we can
+% use math or other variants that look better in normal text.
+
+\catcode`\"=\active
+\def\activedoublequote{{\tt\char34}}
+\let"=\activedoublequote
+\catcode`\~=\active
+\def~{{\tt\char126}}
+\chardef\hat=`\^
+\catcode`\^=\active
+\def^{{\tt \hat}}
+
+\catcode`\_=\active
+\def_{\ifusingtt\normalunderscore\_}
+% Subroutine for the previous macro.
+\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
+
+\catcode`\|=\active
+\def|{{\tt\char124}}
+\chardef \less=`\<
+\catcode`\<=\active
+\def<{{\tt \less}}
+\chardef \gtr=`\>
+\catcode`\>=\active
+\def>{{\tt \gtr}}
+\catcode`\+=\active
+\def+{{\tt \char 43}}
+\catcode`\$=\active
+\def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix
+
+% Set up an active definition for =, but don't enable it most of the time.
+{\catcode`\==\active
+\global\def={{\tt \char 61}}}
+
+\catcode`+=\active
+\catcode`\_=\active
+
+% If a .fmt file is being used, characters that might appear in a file
+% name cannot be active until we have parsed the command line.
+% So turn them off again, and have \everyjob (or @setfilename) turn them on.
+% \otherifyactive is called near the end of this file.
+\def\otherifyactive{\catcode`+=\other \catcode`\_=\other}
+
+\catcode`\@=0
+
+% \rawbackslashxx outputs one backslash character in current font,
+% as in \char`\\.
+\global\chardef\rawbackslashxx=`\\
+
+% \rawbackslash defines an active \ to do \rawbackslashxx.
+% \otherbackslash defines an active \ to be a literal `\' character with
+% catcode other.
+{\catcode`\\=\active
+ @gdef@rawbackslash{@let\=@rawbackslashxx}
+ @gdef@otherbackslash{@let\=@realbackslash}
+}
+
+% \realbackslash is an actual character `\' with catcode other.
+{\catcode`\\=\other @gdef@realbackslash{\}}
+
+% \normalbackslash outputs one backslash in fixed width font.
+\def\normalbackslash{{\tt\rawbackslashxx}}
+
+\catcode`\\=\active
+
+% Used sometimes to turn off (effectively) the active characters
+% even after parsing them.
+@def@turnoffactive{%
+  @let"=@normaldoublequote
+  @let\=@realbackslash
+  @let~=@normaltilde
+  @let^=@normalcaret
+  @let_=@normalunderscore
+  @let|=@normalverticalbar
+  @let<=@normalless
+  @let>=@normalgreater
+  @let+=@normalplus
+  @let$=@normaldollar %$ font-lock fix
+}
+
+% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
+% the literal character `\'.  (Thus, \ is not expandable when this is in
+% effect.)
+%
+@def@normalturnoffactive{@turnoffactive @let\=@normalbackslash}
+
+% Make _ and + \other characters, temporarily.
+% This is canceled by @fixbackslash.
+@otherifyactive
+
+% If a .fmt file is being used, we don't want the `\input texinfo' to show up.
+% That is what \eatinput is for; after that, the `\' should revert to printing
+% a backslash.
+%
+@gdef@eatinput input texinfo{@fixbackslash}
+@global@let\ = @eatinput
+
+% On the other hand, perhaps the file did not have a `\input texinfo'. Then
+% the first `\{ in the file would cause an error. This macro tries to fix
+% that, assuming it is called before the first `\' could plausibly occur.
+% Also back turn on active characters that might appear in the input
+% file name, in case not using a pre-dumped format.
+%
+@gdef@fixbackslash{%
+  @ifx\@eatinput @let\ = @normalbackslash @fi
+  @catcode`+=@active
+  @catcode`@_=@active
+}
+
+% Say @foo, not \foo, in error messages.
+@escapechar = `@@
+
+% These look ok in all fonts, so just make them not special.
+@catcode`@& = @other
+@catcode`@# = @other
+@catcode`@% = @other
+
+@c Set initial fonts.
+@textfonts
+@rm
+
+
+@c Local variables:
+@c eval: (add-hook 'write-file-hooks 'time-stamp)
+@c page-delimiter: "^\\\\message"
+@c time-stamp-start: "def\\\\texinfoversion{"
+@c time-stamp-format: "%:y-%02m-%02d.%02H"
+@c time-stamp-end: "}"
+@c End:
+
+@ignore
+   arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115
+@end ignore
diff --git a/apps/autodist/makedist.in b/apps/autodist/makedist.in
new file mode 100755 (executable)
index 0000000..8979e58
--- /dev/null
@@ -0,0 +1,35 @@
+#!/bin/sh
+#
+# Author: Pekka Riikonen <priikone@silcnet.org>
+#
+# Copyright (C) 2005 Pekka Riikonen
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#   1. Redistributions of source code must retain the above copyright
+#      notice, this list of conditions and the following disclaimer.
+#   2. Redistributions in binary form must reproduce the above copyright
+#      notice, this list of conditions and the following disclaimer in the
+#      documentation and/or other materials provided with the distribution.
+#   3. The name of the author may not be used to endorse or promote
+#      products derived from this software without specific prior written
+#      permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+# NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+AUTODIST="@AUTODIST@"
+
+$AUTODIST $@ -m
diff --git a/apps/autodist/tests/Makefile.am b/apps/autodist/tests/Makefile.am
new file mode 100644 (file)
index 0000000..faf528a
--- /dev/null
@@ -0,0 +1,27 @@
+#
+#  Makefile.am
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
+
+TESTS =                        \
+       autodist1.test          \
+       autodist2.test
+
+clean-local:
+       -rm -rf test
+
+EXTRA_DIST = $(TESTS)
diff --git a/apps/autodist/tests/autodist1.test b/apps/autodist/tests/autodist1.test
new file mode 100755 (executable)
index 0000000..2ea7cc4
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+AUTODIST=../../autodist
+
+rm -rf test
+mkdir test
+
+cd test || exit 1
+
+chmod +x $AUTODIST || exit 1
+
+cat << EOF > configure.ad
+AD_INIT
+#ifdef _DIST_DEFAULT
+AC_CANONICAL_BUILD
+AM_INIT_AUTOMAKE
+AC_PREREQ(2.52)
+AC_CONFIG_HEADERS(config.h)
+AD_INCLUDE_CONFIGURE
+AC_CONFIG_FILES(
+Makefile
+)
+AC_OUTPUT
+echo configure.ad ok
+#endif _DIST_DEFAULT
+EOF
+
+cat << EOF > Makefile.ad
+SUBDIRS=       \
+#ifdef _DIST_NODEF
+       nodef   \
+#endif _DIST_NODEF
+#endif
+EOF
+
+rm -rf distdir subdir
+mkdir -p subdir || exit 1
+
+cat << EOF > subdir/configure.ad
+# subdir/configure.ad fragment
+#ifndef _DIST_NODEF
+echo "_DIST_NODEF ok"
+#endif _DIST_NODEF
+EOF
+
+$AUTODIST -i || exit 1
+if test '!' -d distdir; then
+  echo "error: distdir/ does no exist"
+  exit 1
+fi 
+
+cp -p ../../default distdir || exit 1
+cp -p ../../autodist.conf distdir || exit 1
+
+touch README NEWS AUTHORS ChangeLog
+
+$AUTODIST || exit 1
+
+./configure || exit 1
+make || exit 1
+echo make ok
+
+echo test ok
+
+# Cleanup
+rm -rf subdir distdir
+
diff --git a/apps/autodist/tests/autodist2.test b/apps/autodist/tests/autodist2.test
new file mode 100755 (executable)
index 0000000..3a01e4f
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/sh
+
+AUTODIST=../../autodist
+
+rm -rf test
+mkdir test
+
+cd test || exit 1
+
+chmod +x $AUTODIST || exit 1
+
+cat << EOF > configure.ad
+AD_INIT
+#ifdef _DIST_TEST
+AC_CANONICAL_BUILD
+AM_INIT_AUTOMAKE
+AC_PREREQ(2.52)
+AC_CONFIG_HEADERS(config.h)
+AD_INCLUDE_CONFIGURE
+AC_CONFIG_FILES(
+Makefile
+)
+AC_OUTPUT
+echo configure.ad ok
+#endif _DIST_TEST
+EOF
+
+cat << EOF > Makefile.ad
+SUBDIRS=       \
+#ifndef _DIST_TEST
+       nodef   \
+#endif _DIST_TEST
+#endif
+EOF
+
+rm -rf distdir subdir
+mkdir -p subdir || exit 1
+
+cat << EOF > subdir/configure.ad
+# subdir/configure.ad fragment
+#ifndef _DIST_NODEF
+#ifdef _DIST_TEST
+echo "_DIST_NODEF ok"
+#endif _DIST_TEST
+#endif _DIST_NODEF
+EOF
+
+$AUTODIST -i || exit 1
+if test '!' -d distdir; then
+  echo "error: distdir/ does no exist"
+  exit 1
+fi 
+
+cp -p ../../default distdir || exit 1
+cp -p ../../autodist.conf distdir || exit 1
+
+cat << EOF > distdir/test
+name Test Distribution
+package test-distro
+bug-report test-dist@test.org
+define _DIST_TEST
+EOF
+
+touch README NEWS AUTHORS ChangeLog
+
+echo "inherit test" >> distdir/default
+
+$AUTODIST || exit 1
+$AUTODIST test 1.0 || exit 1
+
+./configure || exit 1
+make || exit 1
+echo make ok
+
+$AUTODIST -m || exit 1
+
+if test '!' -f test-distro-1.0.tar.gz; then
+  echo "error: makedist failed"
+  exit 1
+fi
+
+echo test ok
+
+# Cleanup
+rm -rf subdir distdir
+
index 849e0663c8a95478bf4e424b7c1f9605f29d9e3d..57abce89ebd56946f4b3034c8a5a73066349b4dc 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 # Run this to generate all the initial makefiles, etc.
 
-PKG_NAME="Irssi SILC"
+PKG_NAME="SILC Client"
 
 srcdir=`dirname $0`
 test -z "$srcdir" && srcdir=.
index 85c6a8c19ee9731dbce33a70c6ec7ca06b3e7a76..d925185d1ff6c02766b96e20367b44b610852035 100644 (file)
@@ -7,7 +7,7 @@ if test -n "`grep '^#undef VERSION' config.h.in`"; then
 fi
 
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(Irssi-SILC, 0.8.6+)
+AM_INIT_AUTOMAKE(SILC-Client, 0.8.6+)
 
 AM_MAINTAINER_MODE
 
@@ -664,6 +664,7 @@ AM_CONDITIONAL(HAVE_PERL, test "$want_perl" != "no")
 AM_CONDITIONAL(HAVE_STATIC_PERL, test "$want_perl" = "static")
 AM_CONDITIONAL(NEED_TPARM, test "$need_tparm" = "yes")
 AM_CONDITIONAL(USE_CURSES, test "$want_terminfo" != "yes" -a "$want_termcap" != "yes")
+AM_CONDITIONAL(BUILD_SERVERTEST, false)
 
 # move LIBS to PROG_LIBS so they're not tried to be used when linking eg. perl libraries
 PROG_LIBS=$LIBS
@@ -794,6 +795,7 @@ src/perl/Makefile
 src/perl/common/Makefile.PL
 src/perl/ui/Makefile.PL
 src/perl/textui/Makefile.PL
+src/perl/silc/Makefile.PL
 scripts/Makefile
 docs/Makefile
 docs/help/Makefile
index 1e2dca6f6ec73d1e7dc3571c984991d88b80db64..f7e6d668ba9c79e34b6ea7ac35136c7020479b40 100644 (file)
@@ -55,8 +55,8 @@ info_eol = "false";
 
 # these characters are automatically replaced with specified color
 # (dark grey by default)
-replaces = { "()=" = "%K$*%n"; };
-#replaces = {};
+#replaces = { "()=" = "%K$*%n"; };
+replaces = {};
 
 abstracts = {
   ##
@@ -119,20 +119,30 @@ abstracts = {
   ##
 
   # Generic action
-  action = "%Y* $0 $1-";
+  action = "%c* $*%n ";
 
   # Own sent action
-  ownaction = "%c* $0 $1-";
+  ownaction = "{action $*}";
+
+  # Own sent action with target
+  ownaction_target = "{action $0}%K:%c$1%n ";
+
+  # private action sent by others
+  pvtaction = "%Y(*) $*%n ";
+  pvtaction_query = "%Y* $*%n ";
+
+  # public action sent by others
+  pubaction = "{pvtaction_query $*}";
 
   ##
   ## Notice (/NOTICE command)
   ##
 
   # Generic notice
-  notice = "%C- $0 $1-";
-
-  # Own sent notice
-  ownnotice = "%g- $0 $1-";
+  ownnotice = "%g- $1 -%n ";
+  notice = "%C- $* -%n ";
+  pubnotice_channel = "";
+  pvtnotice_host = "";
 
 
   ##
index 6f0b9f1b980a491a120883ddb00731a9132fcf09..2f2e127b3fd0122527f6d6d3558edbe214284dd0 100644 (file)
@@ -1,6 +1,11 @@
 
 @SYNTAX:action@
 
-Same as ME, but gets channel as an additional parameter. Example: /ACTION silc yawns (This outputs the following to channel silc: * Nick yawns)
+Sends an ACTION to the target.
+For example: /ACTION * sits back. (sends ACTION "sits back" to the current 
+window)
+
+      -channel: interpret <target> as channel name
+      -sign: add signature
 
 See also: ME
index 623c7e548aeaa1409f42fe173c44b34c8f099b36..e664da9c54495c8c55ccecfbc478a3519d6aff5e 100644 (file)
@@ -1,9 +1,9 @@
 
 @SYNTAX:cumode@
 
-This command is used to manage the client's modes on the channel.
-Most of the modes require that the client which changes some
-client's mode must be channel founder or channel operator.  The
+This command is used to manage the users modes on the channel.
+Most of the modes require that the user which changes some
+other user's mode must be channel founder or channel operator.  The
 mode is added by adding + before the option(s) and removed by
 adding - before the option(s).  The following channel user modes
 are available:
@@ -63,7 +63,7 @@ are available:
         Set/unset user as quiet.  When set the user cannot
         talk on the channel, and cannot send messages to
         the channel.  This can be used by channel operator
-        to queit a certain misbehaving user.  The user cannot
+        to quiet a certain misbehaving user.  The user cannot
         unset this mode itself.  This mode cannot be set
         or unset to yourself.
 
index aa274c98bd7965be95bf303891422f7c2582ff99..3593aaf3c1b3e47eb981fd581a87c5e30d80adfb 100644 (file)
@@ -1,18 +1,27 @@
 
 @SYNTAX:kill@
 
-This command can be used for two purpose:  SILC operator may use it
-to remove a client from the network, or user may use it to remove
-its own client entries from the network.
-
-If you are not SILC operator you cannot use this command to remove
-anybody else except yourself from the network.  Only SILC operator
-is able to kill other clients from the network.  When killing your
-own client entry you must provide -pubkey argument to the command.
-For killing your own client from network you also must be connected
-to the same server as your own client entry (the client entry may
-be for example detached client entry).  When using this command as
-SILC operator -pubkey has no effect.
+This command can be used for two purpose:  SILC operator may use it to
+remove a client from the network, or user may use it to remove its own
+client entries from the network.  If you are not SILC operator you cannot
+use this command to remove anybody else except yourself from the network.
+Only SILC operator is able to kill other clients from the network.
+
+Killing own client entry from network:
+
+When killing your own client entry you must provide -pubkey option to the
+command. For killing your own client from network you also must be
+connected to the same server as your own client entry (the client entry
+may be for example detached client entry).  If you are not connected to
+the same server you won't be able to kill the client.  Also, if you have
+changed or lost your old public key pair you won't be able to kill the
+client.
+
+Killing as SILC Operator:
+
+Before killing you must elevate your privileges to SILC Operator by using
+the /SILCOPER command.  After that you can kill a client.  When using this
+command as SILC operator -pubkey option has no effect and can be omitted.
 
 Examples:
 
diff --git a/apps/irssi/docs/help/in/listkeys.in b/apps/irssi/docs/help/in/listkeys.in
new file mode 100644 (file)
index 0000000..549ed69
--- /dev/null
@@ -0,0 +1,11 @@
+
+@SYNTAX:listkeys@
+
+Lists all locally stored public keys.
+
+The options -servers and -clients control whether only server or
+only client keys are shown.
+
+If the filename of a public key is given, details will be displayed
+about the stored public key.
+
diff --git a/apps/irssi/docs/help/in/mmsg.in b/apps/irssi/docs/help/in/mmsg.in
new file mode 100644 (file)
index 0000000..5a945f4
--- /dev/null
@@ -0,0 +1,39 @@
+MMSG [<-sign>] [<-channel>] <target> <file> [<type>  [<encoding>]]
+
+Sends a private data message to other user in the network.  The message
+will be send as a MIME encoded data message.
+
+If -channel option is provided then this command actually send channel
+message to the specified channel.  The message IS NOT private message, it
+is normal channel message.
+
+If the -sign optin is provided, the message will be additionally
+digitally signed and the receiver may verify it with your public key.
+
+Messages that exceed roughly 64k will be fragmented automatically and
+sent as separate messages.  The reassembly of the fragments will be done
+automatically by the recipient.
+
+If no transfer-encoding is given it defaults to binary.  If no 
+content-type is given it is guessed using a MIME magic file.
+
+NOTE: You have to have enabled perl support at compile time, and you need to
+load the perl script silc-mime.pl for this to work!
+
+Settings
+
+  mime_magic            - path to MIME magic file, or internal 
+                          defaults if empty
+  mime_default_encoding - encoding to use if none specified
+  mime_temp_dir         - where to store temporary files
+
+  mime_database         - Mailcap files defining MIME handlers
+  mime_unlink_tempfiles - whether to keep temporary files
+  mime_verbose          - Turn on status messages
+  mime_exec_param       - additional parameters to pass to /EXEC
+
+Examples
+
+  /MMSG Foobar smiley.gif image/gif binary
+  /MMSG -channel silc silc.patch text/x-patch 7bit
+  /MMSG -sign * boing.mp3 audio/mpeg
index fb7c4fc7f625191628c52161687cbd83ccae1315..9db1d2cfa81bb10f2ba492e248faae71ad214b62 100644 (file)
@@ -1,7 +1,8 @@
 
 @SYNTAX:msg@
 
-Sends a private message to other user in the network.
+Sends a private message to other user in the network.  Only you
+and the receipient will be able to see the private message.
 
 It is possible to digitally sign your messages.  The receiver
 may then verify the message with your public key.  By default
@@ -9,13 +10,13 @@ messages are not signed.  If you want your private messages
 to be signed you SMSG command instead of this MSG command.
 
 If -channel option is provided then this command actually
-send channel message to the specified channel.  The message
+sends channel message to the specified channel.  The message
 IS NOT private message, it is normal channel message.  It is
 also possible to digitally sign channel messages by using
 SMSG command or by doing /set sign_channel_messages on, in
 which case _all_ channel messages will be signed.
 
-Example:
+Examples:
 
 /MSG Toni Hi, what's up?
 
index d657288da915bb49a0001b290f3d7b2e97566d8e..95decd803e32bbd41eee43e26ea57163c570319a 100644 (file)
@@ -3,4 +3,3 @@
 
 Changes your nickname.
 
-
index e93d2c2a6aeaadb0501790a77d15bdea9337f5a6..3763cb6072cac09da685b198ed4127318c80a5a8 100644 (file)
@@ -3,6 +3,11 @@
 
 Sends a notice to the nick or the channel. Usually notices
 are used in bots and scripts for different kinds of replies.
+For example: /NOTICE * command executed. (sends NOTICE "command executed" to
+the current window)
+
+      -channel: interpret <target> as channel name
+      -sign: add signature
 
 See also: ACTION
 
index 40dc9c54d3a88d0caf93ac84463f0afb5f1af9f4..d944e796baeb6a84430e4527971197f1c77a4b26 100644 (file)
@@ -1,7 +1,7 @@
 
 @SYNTAX:oper@
 
-Gives you server operator priviledges if the correct
+Gives you the server operator privileges if the correct
 username and passphrase are given. User will be prompted
 for the passphrase if the -pubkey option is not provided.
 
index 806e1b9b71049b7aa2fbd8fcfcb1c60f569dcde9..1a16a8559bfd5a4ca77cfdb8837644adb38a4b53 100644 (file)
@@ -1,7 +1,6 @@
 
 @SYNTAX:ping@
 
-Sends PING to the connected server.
-
-
+Sends PING to the connected server.  It is not possible to ping any
+other server but the one you are directly connected with.
 
diff --git a/apps/irssi/docs/help/in/silcnet.in b/apps/irssi/docs/help/in/silcnet.in
new file mode 100644 (file)
index 0000000..5285db6
--- /dev/null
@@ -0,0 +1,10 @@
+
+@SYNTAX:silcnet@
+
+     -nick, -user, -realname: Specify what nick/user/name to use
+     -host: Specify what host name to use, if you have multiple
+
+Shows and changes the settings of defined SILC networks.
+
+See also: CONNECT
+
index 5247bf46c5bfd2758ea508695c09c59ba10b2ce5..3ddfb8d2532fa3aa24c4d0ae1f1f5cef6af988cb 100644 (file)
@@ -1,12 +1,12 @@
 
 @SYNTAX:silcoper@
 
-Gives you router operator priviledges if the correct
+Gives you the router operator privileges if the correct
 username and passphrase are given. User will be prompted
 for the passphrase if the -pubkey option is not provided.
 
-NOTE: This command works only on router server. It has
-no effect on normal SILC server.
+NOTE: This command works only on router server. It has
+no effect on normal SILC server.
 
 See also: KILL, SCONNECT, CLOSE, OPER
 
index 4f85d37b43294b224fa52b0af9548a97ce4e8155..9ebe1ee07db2e39792213a625ec075258b0fbcd1 100644 (file)
@@ -1,11 +1,11 @@
 
 @SYNTAX:umode@
 
-This command is used to manage client's modes in the network.
-Note that some of the modes the client cannot set itself.
-The mode is added by adding + before the option(s) and removed
-by adding - before the option(s).  The following channel user
-modes are available:
+This command is used to manage user's own modes in the network.  Note that
+some of the modes the user cannot set itself, however any mode can be
+unset by the user.  The mode is added by adding + before the option(s) and
+removed by adding - before the option(s).  The following user modes are
+available:
 
     a        Unset all modes
     s        Unset server operator privileges
index 962b356453b0990d174df30d2e2e087b95395543..6ee12c3803cb3071b2d7119ad0d78ae710c2b00e 100644 (file)
@@ -6,6 +6,11 @@ When the watched nickname appears in the network, leaves the network
 or its user mode is changed you will be notified for this change.  This
 same command can be used also to remove nicknames from being watched.
 
+This command may also be used to watch users by their public keys.
+Since nicknames are not unique in SILC users may frequently change their
+nickname.  By watching them by public key you will be able to keep
+track of your friends regardless of what nickname they use.
+
 Note that some users may have a user mode set that rejects you from
 receiving notifications about them.  Also note that since nicknames are
 not unique it is possible that same nickname matches several users in
@@ -16,5 +21,7 @@ Examples:
 
     /WATCH -add foobar
     /WATCH -del foobar
+    /WATCH -pubkey +/path/to/add/public_key.pub
+    /WATCH -pubkey -/path/to/del/public_key.pub
 
 See also: WHOIS
index b47f9b9ad4f504bd5021a4af4f21882ee1bcd775..57e38717ced01818d4c0da8e8ba8cbd2b9a12be3 100644 (file)
@@ -27,6 +27,9 @@ responds to your request on the behalf of the user if the user
 does not want to respond to you.  In this case the returned
 information may be incomplete.
 
+If the -pubkey option is used WHOIS will only retrieve the clients
+with the corresponding public key.
+
 If you want to send your information in WHOIS you can set the
 information with ATTR command.  See HELP ATTR.
 
index 65f8040e8d12ec6999b2b438f726ecb86b0cb9a0..8da73562dd3e896141436b0026ad12f488e49a84 100644 (file)
@@ -8,9 +8,5 @@ and server. It may also return multiple entries if the
 nickname has been used recently by several people. These
 multiples may be limited by specifying a count to show. 
 
-WHOWAS will work regardless of whether the queried nick
-is in use. If no arguments are given, the client's current
-nickname is used. 
-
 See also: WHOIS
 
index 7c03fad5584641bfe80fffb6bdbef06bff5a85f5..e893b6d657ab3cf0920955816fad19a28691dbe2 100644 (file)
@@ -329,7 +329,7 @@ SILC
 ---
 
 silc-channels.c:
- "mime", SERVER_REC, CHANNEL_REC, char *blob, char *enc, char *type, char *nick
+ "mime", SERVER_REC, WI_ITEM_REC, char *blob, char *nick, int verified
 
 silc-servers.c:
- "mime-send", SERVER_REC, WI_ITEM_REC, char *blob, char *enc, char *type
+ "mime-send", SERVER_REC, int is_channel, char *to, char *blob, int sign
index eafdc27a6f18cf1f56ec51472da7a79219f70e45..38cc48267c9ffbbdee3d771a7bf27c43f55980d6 100644 (file)
@@ -7,6 +7,7 @@ script_DATA = \
        mail.pl \
        beep.pl \
        dns.pl  \
-       mail-maildir.pl
+       mail-maildir.pl \
+       silc-mime.pl
 
 EXTRA_DIST = $(script_DATA)
diff --git a/apps/irssi/scripts/mime-test.pl b/apps/irssi/scripts/mime-test.pl
deleted file mode 100644 (file)
index 23e3840..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-use Irssi;\r
-use MIME::Base64;\r
-\r
-sub sig_mime {\r
-\r
-  my ($server, $channel, $blob, $enc, $type, $nick) = @_;\r
-\r
-  Irssi::print("$enc - $type - $blob->{octets}");\r
-\r
-  if (($enc eq "base64") && ($type eq "image/png")) {\r
-    # just stores the image in /tmp/$nick.png\r
-    open OFILE, '>', "/tmp/" . $nick . ".png";\r
-    print OFILE decode_base64($blob->{data});\r
-    close OFILE;\r
-    Irssi::signal_stop();\r
-  }\r
-\r
-}\r
-\r
-sub cmd_scribble {\r
-\r
-  my ($data, $server, $channel) = @_;\r
-\r
-  return if $server->{chat_type} !~ /^silc$/i;\r
-\r
-  # let's hope, $data is a png image...\r
-  open IFILE, $data;\r
-\r
-  read IFILE, $image, 0xffff;\r
-\r
-  close IFILE;\r
-\r
-  $data = encode_base64($image);\r
-  $octets = length($data);\r
-  Irssi::print($octets);\r
-\r
-  Irssi::signal_emit("mime-send", $server, $channel, $data, \$octets,\r
-       "base64", "image/png");\r
-}\r
-\r
-Irssi::signal_add("mime", "sig_mime");\r
-# /scribble path/to/image.png\r
-Irssi::command_bind("scribble", "cmd_scribble");\r
diff --git a/apps/irssi/scripts/silc-mime.pl b/apps/irssi/scripts/silc-mime.pl
new file mode 100644 (file)
index 0000000..07ea08d
--- /dev/null
@@ -0,0 +1,514 @@
+#!/usr/bin/perl
+
+use vars qw($VERSION %IRSSI);
+
+use Irssi 20020704;
+$VERSION = "1.2";
+%IRSSI = (
+    authors    => "Jochen 'c0ffee' Eisinger",
+    contact    => "c0ffee\@penguin-breeder.org",
+    name       => "SILC2 MIME handler",
+    description => "This script implements MIME handlers for SILC2, according to draft-riikonen-silc-flags-payloads-00",
+    license    => "GPL2 or any later",
+    url                => "http://www.penguin-breeder.org/silc/",
+    changed    => "Wed Aug 29 10:45 CET 2003",
+);
+
+use Irssi::Silc;
+
+use MIME::Parser;
+use Mail::Field;
+use Mail::Cap;
+use File::MMagic;
+use IO::Scalar;
+use IO::File;
+use File::Temp qw/ tempfile /;
+use Sys::Hostname;
+use POSIX qw/ ceil /;
+
+my @mcaps;
+my $magic = new File::MMagic;
+
+## 
+# read_mime_database
+# 
+# Loads all mailcap databases specified in the setting
+# mime_database.  Default is ~/.mailcap and /etc/mailcap in
+# that order.  Function is invoked on startup.
+#
+# MIME Magic Info is also read...
+sub read_mime_database {
+    # read mailcap databases rfc1525
+    foreach (split /\s+/, Irssi::settings_get_str("mime_database")) {
+        if (( -f $_ ) and ( -R $_ )) {
+           Irssi::printformat(MSGLEVEL_CRAP, 'load_mailcap', $_)
+             if Irssi::settings_get_bool("mime_verbose");
+           $mcap = new Mail::Cap $_;
+           push @mcaps, $mcap;
+       } else {
+           Irssi::printformat(MSGLEVEL_CRAP, 'load_mailcap_fail', $_)
+             if Irssi::settings_get_bool("mime_verbose");
+       }
+    }
+
+    $mfile = Irssi::settings_get_str("mime_magic");
+
+    if ($mfile ne "") {
+        Irssi::printformat(MSGLEVEL_CRAP, 'load_mime_magic', $mfile);
+        $magic = File::MMagic::new($mfile);
+    }
+
+    if ( not -d Irssi::settings_get_str("mime_temp_dir")) {
+
+        Irssi::printformat(MSGLEVEL_CRAP, 'no_temp_dir',
+            Irssi::settings_get_str("mime_temp_dir"));
+
+        Irssi::settings_set_str("mime_temp_dir", "/tmp");
+
+    }
+}
+
+##
+# privmsg_get_query
+#
+# get or create query
+#
+sub privmsg_get_query {
+  my ($server, $target, $own) = @_;
+
+  $dest = $server->query_find($target);
+  if (not defined $dest && 
+      (Irssi::level2bits(settings_get_str("autocreate_query_level")) &
+       MSGLEVEL_MSGS) &&
+      (!$own || Irssi::settings_get_bool("autocreate_own_query"))) {
+      $dest = Irssi::Silc::Server::query_create($server->{tag}, $target, 1);
+  }
+
+  return $dest;
+}
+
+##
+# unescape
+#
+# Removes the null-byte escaping from a data block.  Returns the
+# unescaped data.  All data send via mime signals must be escaped.
+sub unescape {
+    my ($escaped) = @_;
+    $escaped =~ s/\001\001/\000/g;
+    $escaped =~ s/\001\002/\001/g;
+
+    return $escaped;
+}
+
+##
+# escape
+#
+# Escapes null-bytes for signal transfer.  Used to transfer binary data
+# in null-terminated strings.  Returns the escaped data.  All data send
+# via mime signals must be escaped.
+sub escape {
+    my ($unescaped) = @_;
+    $unescaped =~ s/\001/\001\002/g;
+    $unescaped =~ s/\000/\001\001/g;
+
+    return $unescaped;
+}
+
+##
+# background_exec
+#
+# fork and execute
+#
+sub background_exec {
+  my ($server, $witem, $signed, $sender, $type, $cmd) = @_;
+
+  if ($signed == -1) {
+    $format = "mime_data_received";
+  } elsif ($signed == 0) {
+    $format = "mime_data_received_signed";
+  } elsif ($signed == 1) {
+    $format = "mime_data_received_unknown";
+  } elsif ($signed == 2) {
+    $format = "mime_data_received_failed";
+  }
+
+  if (not $witem->{type}) {
+    $witem = privmsg_get_query($server, $sender, 0);
+  }
+
+  if ($witem->{type}) {
+    $witem->printformat(MSGLEVEL_CRAP, $format, $sender, $type);
+    $witem->window()->command("EXEC " . Irssi::settings_get_str("mime_exec_param") . " " .
+                   $cmd);
+  } else {
+    Irssi::printformat(MSGLEVEL_CRAP, $format, $sender, $type);
+    Irssi::command("EXEC " . Irssi::settings_get_str("mime_exec_param") . " " .
+                  $cmd);
+  }
+
+}
+
+my %partial;
+
+##
+# process_mime_entity(WI_ITEM_REC, $signed, $sender, MIME::Entity $msg)
+#
+# -1 failure, 0 success
+sub process_mime_entity {
+  my ($server, $witem, $signed, $sender, $entity) = @_;
+
+  my ($mimetype, $fh, $tempfile, $parser, $ret, $io, $mcap, $cmd);  
+
+  $mimetype = Mail::Field->new('Content-type', $entity->head->get('Content-Type'));
+
+  # check whether this is message/partial
+  if ($mimetype->type eq  "message/partial") {
+
+    # without an ID i don't know what stream this is related to
+    if ($mimetype->id eq "") {
+      Irssi::printformat(MSGLEVEL_CRAP, 'message_partial_failure', "no ID");
+      return -1;
+    }
+
+    # the first packet is treated seperatly
+    if ($mimetype->number == 1) {
+
+      # the IDs should be unique
+      if (defined $partial{$mimetype->id}) {
+        Irssi::printformat(MSGLEVEL_CRAP, 'message_partial_failure', "duplicate ID");
+        $fh = $partial{$mimetype->id}{file};
+        $fh->close;
+       unlink $partial{$mimetype->id}{name};
+       undef $partial{$mimetype->id};
+        return -1;
+      }
+
+      # create a new record
+      $partial{$mimetype->id}{received} = 1;
+      ($fh, $partial{$mimetype->id}{name})= tempfile("msg-XXXXXXXX", SUFFIX => ".dat", DIR => Irssi::settings_get_str("mime_temp_dir"));
+      $partial{$mimetype->id}{file} = $fh;
+      $partial{$mimetype->id}{count} = 1;
+      $partial{$mimetype->id}{total} = $mimetype->total;
+      
+    } else { # 2nd and later packets
+
+      # detect unknown IDs
+      if (not defined $partial{$mimetype->id}) {
+        Irssi::printformat(MSGLEVEL_CRAP, 'message_partial_failure', "unknown ID");
+        return -1;
+      }
+      
+      # the 'total' information can be set in any packet,
+      # however it has to be the same all the time
+      if ($mimetype->total > 0) {
+      
+        if (($partial{$mimetype->id}{total} > 0) &&
+            ($partial{$mimetype->id}{total} != $mimetype->total)) {
+          Irssi::printformat(MSGLEVEL_CRAP, 'message_partial_failure', "invalid count");
+         $fh = $partial{$mimetype->id}{file};
+         $fh->close;
+         unlink $partial{$mimetype->id}{name};
+         undef $partial{$mimetype->id};
+         return -1;
+        }
+      
+        $partial{$mimetype->id}{total} = $mimetype->total;
+      
+      }
+      
+      # we expect to receive packets in order
+      if ($mimetype->number != ($partial{$mimetype->id}{count} + 1)) {
+        Irssi::printformat(MSGLEVEL_CRAP, 'message_partial_failure', "invalid sequence number");
+        $fh = $partial{$mimetype->id}{file};
+        $fh->close;
+       unlink $partial{$mimetype->id}{name};
+        undef $partial{$mimetype->id};
+        return -1;
+      }
+      
+      # update our sequence record and save the packet
+      $partial{$mimetype->id}{count} = $mimetype->number;
+
+    }
+
+    # and save the packet
+    $fh = $partial{$mimetype->id}{file};
+    if ($io = $entity->bodyhandle->open("r")) {
+      while (defined($_ = $io->getline)) { print $fh $_ }
+      $io->close;
+    }
+
+    # return if this wasn't the last packet
+    if (($partial{$mimetype->id}{total} == 0) || 
+        ($partial{$mimetype->id}{count} < $partial{$mimetype->id}{total})) {
+      return 1;
+    }
+
+    # last packet...
+    $tempfile = $partial{$mimetype->id}{name};
+    $fh = $partial{$mimetype->id}{file};
+    $fh->close;
+    undef $partial{$mimetype->id};
+
+    $parser = new MIME::Parser;
+    $parser->output_dir(Irssi::settings_get_str("mime_temp_dir"));
+    $mime = $parser->parse_open($tempfile);
+
+    $ret = process_mime_entity($server, $witem, $signed, $sender, $mime);
+
+    $parser->filer->purge;
+    unlink $tempfile;
+    return $ret;
+
+  }
+
+  # we could check for */parityfec (RTP packets) rfc2733, 3009
+
+  # save to temporary file
+  ($fh, $tempfile) = tempfile("msg-XXXXXXXX", SUFFIX => ".dat", DIR => Irssi::settings_get_str("mime_temp_dir"));
+  if ($io = $entity->open("r")) {
+    while (defined($_ = $io->getline)) { print $fh $_; }
+    $io->close;
+  }
+  close $fh;  
+
+  # try to handle it
+  foreach $mcap (@mcaps) {
+
+    $cmd = $mcap->viewCmd($mimetype->type, $tempfile);
+    next if not defined $cmd;
+
+    background_exec($server, $witem, $signed, $sender, $mimetype->type, $cmd);
+    return 1;
+  }
+
+  unlink $tempfile if Irssi::settings_get_bool("mime_unlink_tempfiles");
+  return $mimetype->type;
+}
+
+##
+# sig_mime
+#
+# signal handler for incoming MIME type messages.  If the encoding or
+# the content type are missing or not parsable, they default to binary
+# and application/octet-stream respectivly.  If a decoder for the given
+# transfer encoding is available, the message is decoded.  If a handler
+# for the given content type is available in one of the mailcap databases,
+# the handler is invoked and the signal is stopped.  The mailcap databases
+# are scanned in order of loading.  Temporary files are unlinked if the
+# setting mime_unlink_tempfiles is true.
+sub sig_mime {
+
+    my ($server, $witem, $blob, $sender, $verified) = @_;
+
+    $parser = new MIME::Parser;
+    $parser->output_dir(Irssi::settings_get_str("mime_temp_dir"));
+    $mime = $parser->parse_data(unescape($blob));
+
+    $ret = process_mime_entity($server, $witem, $verified, $sender, $mime);
+
+    $parser->filer->purge;
+
+    if ($ret == 1) {
+        Irssi::signal_stop();
+    } elsif  ($ret == -1) {
+        return;
+    } else {
+       if (not $witem->{type}) {
+         $witem = privmsg_get_query($server, $sender, 0);
+       }
+        $theme = $witem->{theme} || Irssi::current_theme;
+       $format = $theme->get_format("fe-common/silc", "message_data");
+       $format =~ s/\$0/$sender/;
+       $format =~ s/\$1/$ret/;
+       if ($witem->{type}) {
+            $witem->print($theme->format_expand($format));
+        } else {
+            Irssi::print($theme->format_expand($format));
+        }
+        Irssi::signal_stop();
+    }
+}
+
+##
+# cmd_mmsg
+#
+# Sends a file with a given MIME type and transfer encoding.
+#
+# MMSG [<-sign>] [<-channel>] <target> <file> [<type>  [<encoding>]]
+#
+# Sends a private data message to other user in the network.  The message
+# will be send as a MIME encoded data message.
+#
+# If -channel option is provided then this command actually send channel
+# message to the specified channel.  The message IS NOT private message, it
+# is normal channel message.
+#
+# If the -sign optin is provided, the message will be additionally
+# signed.
+#
+# Messages that exceed roughly 64k have to be split up into smaller packets.
+# This is done automatically.
+#
+# If no transfer-encoding is given it defaults to binary or 7bit for messages
+# that have to be split up.
+#
+# If no content-type is given it is guessed using a MIME magic file.
+#
+# Settings
+#
+#   mime_magic            - path to MIME magic file, or internal 
+#                           defaults if empty
+#   mime_default_encoding - encoding to use if none specified
+#   mime_temp_dir         - where to store temporary files
+#
+# Examples
+#
+# /MMSG Foobar smiley.gif image/gif binary
+# /MMSG -channel silc silc.patch text/x-patch 7bit
+# /MMSG * boing.mp3 audio/mpeg
+sub cmd_mmsg {
+    my ($data, $server, $witem) = @_;
+
+    if ($server->{chat_type} ne "SILC") {
+       Irssi::printformat(MSGLEVEL_CRAP, 'mmsg_chattype');
+       return;
+    }
+
+    ($sign, $is_channel, $target, $file, $type, $encoding) =
+        $data =~ /^\s*(?:(-sign)?\s+)?    # match the -sign
+                 \s*(?:(-channel)?\s+)?  # match the -channel
+                 (\*|\S+)\s+             # target
+                 (\S+)                   # filename
+                 (?:\s+(\S+)             # mime type
+                    (?:\s+(\S+))?)?\s*   # encoding
+                $/ix;
+
+    Irssi::printformat(MSGLEVEL_CRAP, 'mmsg_parameters'), return
+        if ($target eq "") or ($file eq "");
+
+    Irssi::printformat(MSGLEVEL_CRAP, 'mmsg_file', $file), return
+        if not ( -f $file );
+
+    $type = $magic->checktype_filename($file)
+        if not defined $type;
+    $encoding = Irssi::settings_get_str("mime_default_encoding")
+        if not defined $encoding;
+
+    # does the target exist? we don't test that... especially the
+    # -channel parameter is ignored :/
+
+    if ($target eq "*") {
+
+      $is_channel = ($witem->{type} eq "CHANNEL" ? "-channel" : "");
+      $target = $witem->{name};
+
+    }
+
+    $entity = new MIME::Entity->build(
+        'MIME-Version' => "1.0",
+       Encoding       => $encoding,
+       Type           => $type,
+       Path           => $file
+    );
+
+    ($fh, $tempfile) = tempfile( DIR => Irssi::settings_get_str("mime_temp_dir"));
+    $entity->print($fh);
+    close $fh;
+
+    $is_channel = (lc($is_channel) eq "-channel" ? 1 : 0);
+    $sign = (lc($sign) eq "-sign" ? 1 : 0);
+
+    if ($is_channel) {
+      $dest = $server->channel_find($target);
+    } else {
+      $dest = privmsg_get_query($server, $target, 1);
+    }
+
+    
+    # 21:27 <@pekka> c0ffee: the core routines will crop the message if it
+    #                doesn't fit.. I would use a bit shorter than the MAX_LEN
+    # 21:28 <@pekka> c0ffee: -1024 bytes is sufficient
+    # 21:28 <@pekka> c0ffee: should be sufficient in all possible cases
+    if ((stat($tempfile))[7] < 0xfbff) {
+      $format = ($sign ? "mime_data_send_signed" : "mime_data_send");
+      if ($dest->{type}) {
+        $dest->printformat(MSGLEVEL_CRAP, $format, $type);
+      } else {
+        Irssi::printformat(MSGLEVEL_CRAP, $format, $type);
+      }
+
+      unlink $tempfile;
+      Irssi::signal_emit("mime-send", $server, \$is_channel,
+                        $target, escape($entity->stringify), \$sign);
+    } else {
+
+      $format = ($sign ? "mime_data_multi_signed" : "mime_data_multi");
+      $chunks = ceil((stat $tempfile)[7] / 0xfb00);
+      if ($dest->{type}) {
+        $dest->printformat(MSGLEVEL_CRAP, $format, $type, $chunks);
+      } else {
+        Irssi::printformat(MSGLEVEL_CRAP, $format, $type, $chunks);
+      }
+
+      open TFILE, $tempfile;
+      $id = sprintf "id-%06d-%08d\@%s", int(rand(65535)), time(), hostname();;
+      $chunks = 0;
+      do {
+        read TFILE, $data, 0xfb00;
+       $chunks++;
+
+        $entity = new MIME::Entity->build(
+            'MIME-Version' => "1.0",
+           Encoding       => "binary",
+           Type           => "message/partial; id=\"$id\"; number=$chunks" . 
+                               (eof(TFILE) ? "; total=$chunks" : ""),
+           Data           => $data
+        );
+        Irssi::signal_emit("mime-send", $server, \$is_channel,
+                               $target, escape($entity->stringify), \$sign);
+
+    } while (!eof(TFILE));
+    close TFILE;
+    
+    unlink $tempfile;
+  }
+}
+
+# Signal handlers
+Irssi::signal_add("mime", "sig_mime");
+
+# Commands
+Irssi::command_bind("mmsg", "cmd_mmsg");
+
+# Settings
+Irssi::settings_add_str("misc", "mime_database", 
+    "$ENV{HOME}/.mailcap /etc/mailcap");
+Irssi::settings_add_bool("misc", "mime_unlink_tempfiles", 1);
+Irssi::settings_add_str("misc", "mime_default_encoding", "binary");
+Irssi::settings_add_bool("misc", "mime_verbose", 0);
+Irssi::settings_add_str("misc", "mime_temp_dir", "/tmp");
+Irssi::settings_add_str("misc", "mime_magic", "");
+Irssi::settings_add_str("misc", "mime_exec_param", "-");
+
+# Init
+Irssi::theme_register(['load_mailcap', 'Loading mailcaps from {hilight $0}',
+       'load_mailcap_fail', 'Couldn\'t find {hilight $0}',
+       'message_partial_failure', 'message/partial: {hilight $0-}',
+       'mmsg_chattype', 'command was not designed for this chat type',
+       'mmsg_parameters', 'not enough parameters given',
+       'mmsg_file', 'File {hilight $0} not found',
+       'load_mime_magic', 'Loading MIME magic types from {hilight $0}',
+       'no_temp_dir', 'Directory {hilight $0} does not exist, defaulting to /tmp',
+       'mime_data_received', '{nick $0} sent "{hilight $1}" data message',
+       'mime_data_received_signed', '{nick $0} sent "{hilight $1}" data message (signature {flag_signed})',
+       'mime_data_received_unknown', '{nick $0} sent "{hilight $1}" data message (signature {flag_unknown})',
+       'mime_data_received_failed', '{nick $0} sent "{hilight $1}" data message (signature {flag_failed})',
+       'mime_data_send', 'sending "{hilight $0}" data message',
+       'mime_data_send_signed', 'sending "{hilight $0}" data message (signature {flag_signed})',
+       'mime_data_multi', 'sending "{hilight $0}" data message ($1 chunks)',
+       'mime_data_multi_signed', 'sending "{hilight $0}" data message ($1 chunks, signature {flag_signed})']);
+
+
+
+read_mime_database();
index c2bd1c69bd57a94aef601fc78943b6c4d2e0fbc6..ba405d717cfc4ef0c8f1656911a2790119c2abf1 100644 (file)
@@ -196,7 +196,6 @@ statusbar = {
 #
 # aes-256-cbc, aes-192-cbc, aes-128-cbc,
 # twofish-256-cbc, twofish-192-cbc, twofish-128-cbc,
-# rc6-256-cbc, rc6-192-cbc, rc6-128-cbc, 
 # cast-256-cbc, cast-192-cbc and cast-128-cbc
 #
 # Available hash functions are (default: sha1):
index 1a89f348df3e661239671ec37969380e6dc0e8cd..ccf0f98c01ebfe480e2f29ea4e6941f88bff56de 100644 (file)
@@ -24,13 +24,19 @@ ADD_INCLUDES = \
 noinst_LIBRARIES = libfe_common_silc.a
 
 libfe_common_silc_a_SOURCES = \
-       fe-channels.c \
+       fe-silc-channels.c \
        fe-common-silc.c \
        module-formats.c \
        silc-modules.c \
-       fe-messages.c
+       fe-silc-messages.c \
+       fe-silcnet.c \
+       fe-silc-queries.c
 
 noinst_HEADERS = \
        module-formats.h \
+       fe-silc-channels.h \
+       fe-silc-messages.h \
+       fe-silc-queries.h \
+       fe-silcnet.h \
        fe-common-silc.h \
        module.h
index 51047a005396ddf52936115d787c034e88d34a7f..d1fc3543787e720d194b771f47aad243c0509662 100644 (file)
 #include "signals.h"
 #include "themes.h"
 
-void fe_silc_channels_init(void);
-void fe_silc_channels_deinit(void);
+#include "fe-silcnet.h"
+#include "fe-silc-messages.h"
+#include "fe-silc-queries.h"
+#include "fe-silc-channels.h"
+
 
 void fe_silc_modules_init(void);
 void fe_silc_modules_deinit(void);
 
-void fe_silc_messages_init(void);
-void fe_silc_messages_deinit(void);
-
 void fe_silc_init(void)
 {
   theme_register(fecommon_silc_formats);
@@ -40,15 +40,19 @@ void fe_silc_init(void)
   fe_silc_channels_init();
   fe_silc_modules_init();
   fe_silc_messages_init();
+  fe_silc_queries_init();
+  fe_silcnet_init();
 
   module_register("silc", "fe");
 }
 
 void fe_silc_deinit(void)
 {
+  fe_silc_queries_deinit();
   fe_silc_messages_deinit();
   fe_silc_modules_deinit();
   fe_silc_channels_deinit();
+  fe_silcnet_deinit();
 
   theme_unregister();
 }
diff --git a/apps/irssi/src/fe-common/silc/fe-messages.c b/apps/irssi/src/fe-common/silc/fe-messages.c
deleted file mode 100644 (file)
index 41e0514..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-
-  fe-messages.c
-
-  Author: Jochen Eisinger <c0ffee@penguin-breeder.org>
-
-  Copyright (C) 2002 Jochen Eisinger
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
-
-*/
-
-#include "module.h"
-#include "modules.h"
-#include "signals.h"
-#include "themes.h"
-#include "levels.h"
-#include "misc.h"
-#include "special-vars.h"
-#include "settings.h"
-
-#include "servers.h"
-#include "channels.h"
-#include "nicklist.h"
-#include "ignore.h"
-
-#include "window-items.h"
-#include "fe-queries.h"
-#include "fe-messages.h"
-#include "hilight-text.h"
-#include "printtext.h"
-#include "module-formats.h"
-
-#define VERIFIED_MSG(v,msg) (v == SILC_MSG_SIGNED_VERIFIED ? \
-                               msg##_SIGNED : (v == SILC_MSG_SIGNED_UNKNOWN ? \
-                               msg##_UNKNOWN : msg##_FAILED))
-
-static void sig_signed_message_public(SERVER_REC * server, const char *msg,
-                                     const char *nick,
-                                     const char *address,
-                                     const char *target,
-                                     int verified)
-{
-  CHANNEL_REC *chanrec;
-  NICK_REC *nickrec = NULL; /* we cheat here a little to keep the limit of 
-                              6 parameters to a signal handler ... */
-  const char *nickmode, *printnick;
-  int for_me, print_channel, level;
-  char *color, *freemsg = NULL;
-
-  /* NOTE: this may return NULL if some channel is just closed with
-     /WINDOW CLOSE and server still sends the few last messages */
-  chanrec = channel_find(server, target);
-  if (nickrec == NULL && chanrec != NULL)
-    nickrec = nicklist_find(chanrec, nick);
-
-  for_me = !settings_get_bool("hilight_nick_matches") ? FALSE :
-      nick_match_msg(chanrec, msg, server->nick);
-  color = for_me ? NULL :
-      hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC,
-                        msg);
-
-  print_channel = chanrec == NULL ||
-      !window_item_is_active((WI_ITEM_REC *) chanrec);
-  if (!print_channel && settings_get_bool("print_active_channel") &&
-      window_item_window((WI_ITEM_REC *) chanrec)->items->next != NULL)
-    print_channel = TRUE;
-
-  level = MSGLEVEL_PUBLIC;
-  if (for_me || color != NULL)
-    level |= MSGLEVEL_HILIGHT;
-
-  if (settings_get_bool("emphasis"))
-    msg = freemsg = expand_emphasis((WI_ITEM_REC *) chanrec, msg);
-
-  /* get nick mode & nick what to print the msg with
-     (in case there's multiple identical nicks) */
-  nickmode = channel_get_nickmode(chanrec, nick);
-  printnick = nickrec == NULL ? nick :
-      g_hash_table_lookup(printnicks, nickrec);
-  if (printnick == NULL)
-    printnick = nick;
-
-  if (!print_channel) {
-    /* message to active channel in window */
-    if (color != NULL) {
-      /* highlighted nick */
-      printformat_module("fe-common/silc", server, target,
-                        level, VERIFIED_MSG(verified, SILCTXT_PUBMSG_HILIGHT),
-                        color, printnick, msg, nickmode);
-    } else {
-      printformat_module("fe-common/silc", server, target, level,
-                        for_me ? VERIFIED_MSG(verified, SILCTXT_PUBMSG_ME) :
-                                 VERIFIED_MSG(verified,SILCTXT_PUBMSG),
-                        printnick, msg, nickmode);
-    }
-  } else {
-    /* message to not existing/active channel */
-    if (color != NULL) {
-      /* highlighted nick */
-      printformat_module("fe-common/silc", server, target, level,
-                        VERIFIED_MSG(verified, SILCTXT_PUBMSG_HILIGHT_CHANNEL),
-                        color, printnick, target, msg, nickmode);
-    } else {
-      printformat_module("fe-common/silc", server, target, level,
-                        for_me ? VERIFIED_MSG(verified, SILCTXT_PUBMSG_ME_CHANNEL) :
-                        VERIFIED_MSG(verified, SILCTXT_PUBMSG_CHANNEL),
-                        printnick, target, msg, nickmode);
-    }
-  }
-
-  g_free_not_null(freemsg);
-  g_free_not_null(color);
-}
-
-static void sig_signed_message_private(SERVER_REC * server,
-                                      const char *msg, const char *nick,
-                                      const char *address, int verified)
-{
-  QUERY_REC *query;
-  char *freemsg = NULL;
-
-  query = query_find(server, nick);
-
-  if (settings_get_bool("emphasis"))
-    msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg);
-
-  printformat_module("fe-common/silc", server, nick, MSGLEVEL_MSGS,
-                    query == NULL ? VERIFIED_MSG(verified, SILCTXT_MSG_PRIVATE) :
-                    VERIFIED_MSG(verified, SILCTXT_MSG_PRIVATE_QUERY), nick, address, msg);
-
-  g_free_not_null(freemsg);
-}
-
-static void sig_signed_message_own_public(SERVER_REC * server,
-                                         const char *msg,
-                                         const char *target)
-{
-  WINDOW_REC *window;
-  CHANNEL_REC *channel;
-  const char *nickmode;
-  char *freemsg = NULL;
-  int print_channel;
-
-  channel = channel_find(server, target);
-  if (channel != NULL)
-    target = channel->visible_name;
-
-  nickmode = channel_get_nickmode(channel, server->nick);
-
-  window = channel == NULL ? NULL :
-      window_item_window((WI_ITEM_REC *) channel);
-
-  print_channel = window == NULL ||
-      window->active != (WI_ITEM_REC *) channel;
-
-  if (!print_channel && settings_get_bool("print_active_channel") &&
-      window != NULL && g_slist_length(window->items) > 1)
-    print_channel = TRUE;
-
-  if (settings_get_bool("emphasis"))
-    msg = freemsg = expand_emphasis((WI_ITEM_REC *) channel, msg);
-
-  if (!print_channel) {
-    printformat_module("fe-common/silc", server, target,
-                      MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
-                      MSGLEVEL_NO_ACT, SILCTXT_OWN_MSG_SIGNED, server->nick, msg,
-                      nickmode);
-  } else {
-    printformat_module("fe-common/silc", server, target,
-                      MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
-                      MSGLEVEL_NO_ACT, SILCTXT_OWN_MSG_CHANNEL_SIGNED,
-                      server->nick, target, msg, nickmode);
-  }
-
-  g_free_not_null(freemsg);
-}
-
-static void sig_signed_message_own_private(SERVER_REC * server,
-                                          const char *msg,
-                                          const char *target,
-                                          const char *origtarget)
-{
-  QUERY_REC *query;
-  char *freemsg = NULL;
-
-  g_return_if_fail(server != NULL);
-  g_return_if_fail(msg != NULL);
-
-  if (target == NULL) {
-    /* this should only happen if some special target failed and
-       we should display some error message. currently the special
-       targets are only ',' and '.'. */
-    g_return_if_fail(strcmp(origtarget, ",") == 0 ||
-                    strcmp(origtarget, ".") == 0);
-
-    printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CLIENTNOTICE,
-                      *origtarget == ',' ? SILCTXT_NO_MSGS_GOT :
-                      SILCTXT_NO_MSGS_SENT);
-    signal_stop();
-    return;
-  }
-
-  query = privmsg_get_query(server, target, TRUE, MSGLEVEL_MSGS);
-
-  if (settings_get_bool("emphasis"))
-    msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg);
-
-  printformat_module("fe-common/silc", server, target,
-                    MSGLEVEL_MSGS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
-                    query == NULL ? SILCTXT_OWN_MSG_PRIVATE_SIGNED :
-                    SILCTXT_OWN_MSG_PRIVATE_QUERY_SIGNED, target, msg,
-                    server->nick);
-
-  g_free_not_null(freemsg);
-}
-
-void fe_silc_messages_init(void)
-{
-  signal_add_last("message signed_public",
-                 (SIGNAL_FUNC) sig_signed_message_public);
-  signal_add_last("message signed_private",
-                 (SIGNAL_FUNC) sig_signed_message_private);
-  signal_add_last("message signed_own_public",
-                 (SIGNAL_FUNC) sig_signed_message_own_public);
-  signal_add_last("message signed_own_private",
-                 (SIGNAL_FUNC) sig_signed_message_own_private);
-}
-
-void fe_silc_messages_deinit(void)
-{
-  signal_remove("message signed_public",
-               (SIGNAL_FUNC) sig_signed_message_public);
-  signal_remove("message signed_private",
-               (SIGNAL_FUNC) sig_signed_message_private);
-  signal_remove("message signed_own_public",
-               (SIGNAL_FUNC) sig_signed_message_own_public);
-  signal_remove("message signed_own_private",
-               (SIGNAL_FUNC) sig_signed_message_own_private);
-}
similarity index 96%
rename from apps/irssi/src/fe-common/silc/fe-channels.c
rename to apps/irssi/src/fe-common/silc/fe-silc-channels.c
index 47696cfc5ac3a62d0cd14531a15d9e4c22d8533a..538d9ff6c40d1a205358509ac70262c970290e2c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- fe-channels.c : irssi
+ fe-silc-channels.c : irssi
 
     Copyright (C) 2000 Timo Sirainen
 
diff --git a/apps/irssi/src/fe-common/silc/fe-silc-channels.h b/apps/irssi/src/fe-common/silc/fe-silc-channels.h
new file mode 100644 (file)
index 0000000..7492f4a
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __FE_SILC_CHANNELS_H
+#define __FE_SILC_CHANNELS_H
+
+void fe_silc_channels_init();
+void fe_silc_channels_deinit();
+
+#endif
diff --git a/apps/irssi/src/fe-common/silc/fe-silc-messages.c b/apps/irssi/src/fe-common/silc/fe-silc-messages.c
new file mode 100644 (file)
index 0000000..475c9e9
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+
+  fe-silc-messages.c
+
+  Author: Jochen Eisinger <c0ffee@penguin-breeder.org>
+
+  Copyright (C) 2002 Jochen Eisinger
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
+
+*/
+
+#include "module.h"
+#include "modules.h"
+#include "signals.h"
+#include "themes.h"
+#include "levels.h"
+#include "misc.h"
+#include "special-vars.h"
+#include "settings.h"
+
+#include "servers.h"
+#include "channels.h"
+#include "nicklist.h"
+#include "ignore.h"
+
+#include "window-items.h"
+#include "fe-queries.h"
+#include "fe-messages.h"
+#include "hilight-text.h"
+#include "printtext.h"
+#include "module-formats.h"
+
+#define VERIFIED_MSG(v,msg) (v == SILC_MSG_SIGNED_VERIFIED ? \
+                               msg##_SIGNED : (v == SILC_MSG_SIGNED_UNKNOWN ? \
+                               msg##_UNKNOWN : msg##_FAILED))
+
+#define VERIFIED_MSG2(v,msg) (v >= 0 ? VERIFIED_MSG(v,msg) : msg)
+
+static void sig_signed_message_public(SERVER_REC * server, const char *msg,
+                                     const char *nick,
+                                     const char *address,
+                                     const char *target,
+                                     int verified)
+{
+  CHANNEL_REC *chanrec;
+  NICK_REC *nickrec = NULL; /* we cheat here a little to keep the limit of 
+                              6 parameters to a signal handler ... */
+  const char *nickmode, *printnick;
+  int for_me, print_channel, level;
+  char *color, *freemsg = NULL;
+
+  /* NOTE: this may return NULL if some channel is just closed with
+     /WINDOW CLOSE and server still sends the few last messages */
+  chanrec = channel_find(server, target);
+  if (nickrec == NULL && chanrec != NULL)
+    nickrec = nicklist_find(chanrec, nick);
+
+  for_me = !settings_get_bool("hilight_nick_matches") ? FALSE :
+      nick_match_msg(chanrec, msg, server->nick);
+  color = for_me ? NULL :
+      hilight_match_nick(server, target, nick, address, MSGLEVEL_PUBLIC,
+                        msg);
+
+  print_channel = chanrec == NULL ||
+      !window_item_is_active((WI_ITEM_REC *) chanrec);
+  if (!print_channel && settings_get_bool("print_active_channel") &&
+      window_item_window((WI_ITEM_REC *) chanrec)->items->next != NULL)
+    print_channel = TRUE;
+
+  level = MSGLEVEL_PUBLIC;
+  if (for_me || color != NULL)
+    level |= MSGLEVEL_HILIGHT;
+
+  if (settings_get_bool("emphasis"))
+    msg = freemsg = expand_emphasis((WI_ITEM_REC *) chanrec, msg);
+
+  /* get nick mode & nick what to print the msg with
+     (in case there's multiple identical nicks) */
+  nickmode = channel_get_nickmode(chanrec, nick);
+  printnick = nickrec == NULL ? nick :
+      g_hash_table_lookup(printnicks, nickrec);
+  if (printnick == NULL)
+    printnick = nick;
+
+  if (!print_channel) {
+    /* message to active channel in window */
+    if (color != NULL) {
+      /* highlighted nick */
+      printformat_module("fe-common/silc", server, target,
+                        level, VERIFIED_MSG(verified, SILCTXT_PUBMSG_HILIGHT),
+                        color, printnick, msg, nickmode);
+    } else {
+      printformat_module("fe-common/silc", server, target, level,
+                        for_me ? VERIFIED_MSG(verified, SILCTXT_PUBMSG_ME) :
+                                 VERIFIED_MSG(verified,SILCTXT_PUBMSG),
+                        printnick, msg, nickmode);
+    }
+  } else {
+    /* message to not existing/active channel */
+    if (color != NULL) {
+      /* highlighted nick */
+      printformat_module("fe-common/silc", server, target, level,
+                        VERIFIED_MSG(verified, SILCTXT_PUBMSG_HILIGHT_CHANNEL),
+                        color, printnick, target, msg, nickmode);
+    } else {
+      printformat_module("fe-common/silc", server, target, level,
+                        for_me ? VERIFIED_MSG(verified, SILCTXT_PUBMSG_ME_CHANNEL) :
+                        VERIFIED_MSG(verified, SILCTXT_PUBMSG_CHANNEL),
+                        printnick, target, msg, nickmode);
+    }
+  }
+
+  g_free_not_null(freemsg);
+  g_free_not_null(color);
+}
+
+static void sig_signed_message_own_public(SERVER_REC * server,
+                                         const char *msg,
+                                         const char *target)
+{
+  WINDOW_REC *window;
+  CHANNEL_REC *channel;
+  const char *nickmode;
+  char *freemsg = NULL;
+  int print_channel;
+
+  channel = channel_find(server, target);
+  if (channel != NULL)
+    target = channel->visible_name;
+
+  nickmode = channel_get_nickmode(channel, server->nick);
+
+  window = channel == NULL ? NULL :
+      window_item_window((WI_ITEM_REC *) channel);
+
+  print_channel = window == NULL ||
+      window->active != (WI_ITEM_REC *) channel;
+
+  if (!print_channel && settings_get_bool("print_active_channel") &&
+      window != NULL && g_slist_length(window->items) > 1)
+    print_channel = TRUE;
+
+  if (settings_get_bool("emphasis"))
+    msg = freemsg = expand_emphasis((WI_ITEM_REC *) channel, msg);
+
+  if (!print_channel) {
+    printformat_module("fe-common/silc", server, target,
+                      MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
+                      MSGLEVEL_NO_ACT, SILCTXT_OWN_MSG_SIGNED, server->nick, msg,
+                      nickmode);
+  } else {
+    printformat_module("fe-common/silc", server, target,
+                      MSGLEVEL_PUBLIC | MSGLEVEL_NOHILIGHT |
+                      MSGLEVEL_NO_ACT, SILCTXT_OWN_MSG_CHANNEL_SIGNED,
+                      server->nick, target, msg, nickmode);
+  }
+
+  g_free_not_null(freemsg);
+}
+
+static void sig_signed_message_private(SERVER_REC * server,
+                                      const char *msg, const char *nick,
+                                      const char *address, int verified)
+{
+  QUERY_REC *query;
+  char *freemsg = NULL;
+
+  query = query_find(server, nick);
+
+  if (settings_get_bool("emphasis"))
+    msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg);
+
+  printformat_module("fe-common/silc", server, nick, MSGLEVEL_MSGS,
+                    query == NULL ? VERIFIED_MSG(verified, SILCTXT_MSG_PRIVATE) :
+                    VERIFIED_MSG(verified, SILCTXT_MSG_PRIVATE_QUERY), nick, address, msg);
+
+  g_free_not_null(freemsg);
+}
+
+static void sig_signed_message_own_private(SERVER_REC * server,
+                                          const char *msg,
+                                          const char *target,
+                                          const char *origtarget)
+{
+  QUERY_REC *query;
+  char *freemsg = NULL;
+
+  g_return_if_fail(server != NULL);
+  g_return_if_fail(msg != NULL);
+
+  if (target == NULL) {
+    /* this should only happen if some special target failed and
+       we should display some error message. currently the special
+       targets are only ',' and '.'. */
+    g_return_if_fail(strcmp(origtarget, ",") == 0 ||
+                    strcmp(origtarget, ".") == 0);
+
+    printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+                      *origtarget == ',' ? SILCTXT_NO_MSGS_GOT :
+                      SILCTXT_NO_MSGS_SENT);
+    signal_stop();
+    return;
+  }
+
+  query = privmsg_get_query(server, target, TRUE, MSGLEVEL_MSGS);
+
+  if (settings_get_bool("emphasis"))
+    msg = freemsg = expand_emphasis((WI_ITEM_REC *) query, msg);
+
+  printformat_module("fe-common/silc", server, target,
+                    MSGLEVEL_MSGS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
+                    query == NULL ? SILCTXT_OWN_MSG_PRIVATE_SIGNED :
+                    SILCTXT_OWN_MSG_PRIVATE_QUERY_SIGNED, target, msg,
+                    server->nick);
+
+  g_free_not_null(freemsg);
+}
+
+static void sig_message_own_action_all(SERVER_REC *server, 
+                                       const char *msg, const char *target,
+                                       bool is_channel, bool is_signed)
+{
+  void *item;
+  char *freemsg = NULL;
+
+  if (is_channel)
+    item = channel_find(server, target);
+  else
+    item = query_find(server, target);
+
+  if (settings_get_bool("emphasis"))
+    msg = freemsg = expand_emphasis(item, msg);
+
+  printformat(server, target,
+             MSGLEVEL_ACTIONS | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT |
+             (is_channel ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS),
+             item != NULL ? 
+             (is_signed ? SILCTXT_OWN_ACTION_SIGNED : SILCTXT_OWN_ACTION) :
+             (is_signed ? SILCTXT_OWN_ACTION_TARGET_SIGNED :
+                          SILCTXT_OWN_ACTION_TARGET),
+             server->nick, msg, target);
+
+  g_free_not_null(freemsg);
+}
+
+static void sig_message_own_action(SERVER_REC *server, const char *msg,
+                                  const char *target)
+{
+  sig_message_own_action_all(server, msg, target, TRUE, FALSE);
+}
+
+static void sig_message_own_private_action(SERVER_REC *server,
+                                          const char *msg, const char *target)
+{
+  sig_message_own_action_all(server, msg, target, FALSE, FALSE);
+}
+
+static void sig_message_own_action_signed(SERVER_REC *server,
+                                         const char *msg, const char *target)
+{
+  sig_message_own_action_all(server, msg, target, TRUE, TRUE);
+}
+
+static void sig_message_own_private_action_signed(SERVER_REC *server,
+                                         const char *msg, const char *target)
+{
+  sig_message_own_action_all(server, msg, target, FALSE, TRUE);
+}
+
+static void sig_message_action_all(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target, int is_channel,
+                                  int verified)
+{
+  void *item;
+  char *freemsg = NULL;
+  int level;
+
+  level = MSGLEVEL_ACTIONS |
+         (is_channel ? MSGLEVEL_PUBLIC : MSGLEVEL_MSGS);
+
+  if (ignore_check(server, nick, address, target, msg, level))
+    return;
+
+  if (is_channel)
+    item = channel_find(server, target);
+  else
+    item = privmsg_get_query(server, nick, FALSE, level);
+
+  if (settings_get_bool("emphasis"))
+    msg = freemsg = expand_emphasis(item, msg);
+
+  if (is_channel) {
+    /* channel action */ 
+    if (window_item_is_active(item)) {
+      /* message to active channel in window */
+      printformat(server, target, level,
+                 VERIFIED_MSG2(verified, SILCTXT_ACTION_PUBLIC), 
+                 nick, target, msg);
+    } else {
+      /* message to not existing/active channel */
+      printformat(server, target, level,
+                 VERIFIED_MSG2(verified, SILCTXT_ACTION_PUBLIC_CHANNEL),
+                 nick, target, msg);
+    }
+  } else {
+    /* private action */
+    printformat(server, nick, MSGLEVEL_ACTIONS | MSGLEVEL_MSGS,
+               item == NULL ? VERIFIED_MSG2(verified, SILCTXT_ACTION_PRIVATE) :
+               VERIFIED_MSG2(verified, SILCTXT_ACTION_PRIVATE_QUERY),
+               nick, address == NULL ? "" : address, msg);
+  }
+
+  g_free_not_null(freemsg);
+}
+
+static void sig_message_action(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target)
+{
+  sig_message_action_all(server, msg, nick, address, target, TRUE, -1);
+}
+
+static void sig_message_private_action(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target)
+{
+  sig_message_action_all(server, msg, nick, address, target, FALSE, -1);
+}
+
+static void sig_message_action_signed(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target, int verified)
+{
+  sig_message_action_all(server, msg, nick, address, target, TRUE, verified);
+}
+
+static void sig_message_private_action_signed(SERVER_REC *server,
+                                  const char *msg, const char *nick,
+                                  const char *address, const char *target,
+                                  int verified)
+{
+  sig_message_action_all(server, msg, nick, address, target, FALSE, verified);
+}
+
+static void sig_message_own_notice_all(SERVER_REC *server, 
+                                       const char *msg, const char *target,
+                                       bool is_signed)
+{
+  printformat(server, target,
+             MSGLEVEL_NOTICES | MSGLEVEL_NOHILIGHT | MSGLEVEL_NO_ACT,
+             (is_signed ? SILCTXT_OWN_NOTICE_SIGNED : SILCTXT_OWN_NOTICE),
+             target, msg);
+}
+
+static void sig_message_own_notice(SERVER_REC *server, const char *msg,
+                                  const char *target)
+{
+  sig_message_own_notice_all(server, msg, target, FALSE);
+}
+
+static void sig_message_own_notice_signed(SERVER_REC *server,
+                                         const char *msg, const char *target)
+{
+  sig_message_own_notice_all(server, msg, target, TRUE);
+}
+
+static void sig_message_notice_all(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target, int is_channel,
+                                  int verified)
+{
+  if (ignore_check(server, nick, address, target, msg, MSGLEVEL_NOTICES))
+    return;
+
+  if (is_channel) {
+    /* channel notice */ 
+      printformat(server, target, MSGLEVEL_NOTICES,
+                 VERIFIED_MSG2(verified, SILCTXT_NOTICE_PUBLIC), 
+                 nick, target, msg);
+  } else {
+    /* private notice */
+    printformat(server, nick, MSGLEVEL_NOTICES,
+               VERIFIED_MSG2(verified, SILCTXT_NOTICE_PRIVATE),
+               nick, address == NULL ? "" : address, msg);
+  }
+
+}
+
+static void sig_message_notice(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target)
+{
+  sig_message_notice_all(server, msg, nick, address, target, TRUE, -1);
+}
+
+static void sig_message_private_notice(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target)
+{
+  sig_message_notice_all(server, msg, nick, address, target, FALSE, -1);
+}
+
+static void sig_message_notice_signed(SERVER_REC *server, const char *msg,
+                                  const char *nick, const char *address,
+                                  const char *target, int verified)
+{
+  sig_message_notice_all(server, msg, nick, address, target, TRUE, verified);
+}
+
+static void sig_message_private_notice_signed(SERVER_REC *server,
+                                  const char *msg, const char *nick,
+                                  const char *address, const char *target,
+                                  int verified)
+{
+  sig_message_notice_all(server, msg, nick, address, target, FALSE, verified);
+}
+
+void fe_silc_messages_init(void)
+{
+  signal_add_last("message signed_public",
+                 (SIGNAL_FUNC) sig_signed_message_public);
+  signal_add_last("message signed_own_public",
+                 (SIGNAL_FUNC) sig_signed_message_own_public);
+  signal_add_last("message signed_private",
+                 (SIGNAL_FUNC) sig_signed_message_private);
+  signal_add_last("message signed_own_private",
+                 (SIGNAL_FUNC) sig_signed_message_own_private);
+
+  signal_add_last("message silc own_action",
+                 (SIGNAL_FUNC) sig_message_own_action);
+  signal_add_last("message silc action",
+                 (SIGNAL_FUNC) sig_message_action);
+  signal_add_last("message silc signed_own_action",
+                 (SIGNAL_FUNC) sig_message_own_action_signed);
+  signal_add_last("message silc signed_action",
+                 (SIGNAL_FUNC) sig_message_action_signed);
+  signal_add_last("message silc own_private_action",
+                 (SIGNAL_FUNC) sig_message_own_private_action);
+  signal_add_last("message silc private_action",
+                 (SIGNAL_FUNC) sig_message_private_action);
+  signal_add_last("message silc signed_own_private_action",
+                 (SIGNAL_FUNC) sig_message_own_private_action_signed);
+  signal_add_last("message silc signed_private_action",
+                 (SIGNAL_FUNC) sig_message_private_action_signed);
+
+  signal_add_last("message silc own_notice",
+                 (SIGNAL_FUNC) sig_message_own_notice);
+  signal_add_last("message silc notice",
+                 (SIGNAL_FUNC) sig_message_notice);
+  signal_add_last("message silc signed_own_notice",
+                 (SIGNAL_FUNC) sig_message_own_notice_signed);
+  signal_add_last("message silc signed_notice",
+                 (SIGNAL_FUNC) sig_message_notice_signed);
+  signal_add_last("message silc own_private_notice",
+                 (SIGNAL_FUNC) sig_message_own_notice);
+  signal_add_last("message silc private_notice",
+                 (SIGNAL_FUNC) sig_message_private_notice);
+  signal_add_last("message silc signed_own_private_notice",
+                 (SIGNAL_FUNC) sig_message_own_notice_signed);
+  signal_add_last("message silc signed_private_notice",
+                 (SIGNAL_FUNC) sig_message_private_notice_signed);
+}
+
+void fe_silc_messages_deinit(void)
+{
+  signal_remove("message signed_public",
+               (SIGNAL_FUNC) sig_signed_message_public);
+  signal_remove("message signed_own_public",
+               (SIGNAL_FUNC) sig_signed_message_own_public);
+  signal_remove("message signed_private",
+               (SIGNAL_FUNC) sig_signed_message_private);
+  signal_remove("message signed_own_private",
+               (SIGNAL_FUNC) sig_signed_message_own_private);
+
+  signal_remove("message silc own_action",
+               (SIGNAL_FUNC) sig_message_own_action);
+  signal_remove("message silc action",
+               (SIGNAL_FUNC) sig_message_action);
+  signal_remove("message silc signed_own_action",
+               (SIGNAL_FUNC) sig_message_own_action_signed);
+  signal_remove("message silc signed_action",
+               (SIGNAL_FUNC) sig_message_action_signed);
+  signal_remove("message silc own_private_action",
+               (SIGNAL_FUNC) sig_message_own_private_action);
+  signal_remove("message silc private_action",
+               (SIGNAL_FUNC) sig_message_private_action);
+  signal_remove("message silc signed_own_private_action",
+               (SIGNAL_FUNC) sig_message_own_private_action_signed);
+  signal_remove("message silc signed_private_action",
+               (SIGNAL_FUNC) sig_message_private_action_signed);
+
+  signal_remove("message silc own_notice",
+               (SIGNAL_FUNC) sig_message_own_notice);
+  signal_remove("message silc notice",
+               (SIGNAL_FUNC) sig_message_notice);
+  signal_remove("message silc signed_own_notice",
+               (SIGNAL_FUNC) sig_message_own_notice_signed);
+  signal_remove("message silc signed_notice",
+               (SIGNAL_FUNC) sig_message_notice_signed);
+  signal_remove("message silc own_private_notice",
+               (SIGNAL_FUNC) sig_message_own_notice);
+  signal_remove("message silc private_notice",
+               (SIGNAL_FUNC) sig_message_private_notice);
+  signal_remove("message silc signed_own_private_notice",
+               (SIGNAL_FUNC) sig_message_own_notice_signed);
+  signal_remove("message silc signed_private_notice",
+               (SIGNAL_FUNC) sig_message_private_notice_signed);
+}
diff --git a/apps/irssi/src/fe-common/silc/fe-silc-messages.h b/apps/irssi/src/fe-common/silc/fe-silc-messages.h
new file mode 100644 (file)
index 0000000..300bb9d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __FE_SILC_MESSAGES_H
+#define __FE_SILC_MESSAGES_H
+
+void fe_silc_messages_init();
+void fe_silc_messages_deinit();
+
+#endif
diff --git a/apps/irssi/src/fe-common/silc/fe-silc-queries.c b/apps/irssi/src/fe-common/silc/fe-silc-queries.c
new file mode 100644 (file)
index 0000000..405fd91
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+
+  fe-silc-queries.c
+
+  Author: Jochen Eisinger <c0ffee@penguin-breeder.org>
+
+  Copyright (C) 2003 Jochen Eisinger
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
+
+*/
+
+#include "module.h"
+#include "modules.h"
+#include "signals.h"
+#include "themes.h"
+#include "levels.h"
+#include "misc.h"
+#include "special-vars.h"
+#include "settings.h"
+
+#include "servers.h"
+#include "channels.h"
+#include "nicklist.h"
+#include "ignore.h"
+
+#include "window-items.h"
+#include "fe-queries.h"
+#include "fe-messages.h"
+#include "hilight-text.h"
+#include "printtext.h"
+#include "module-formats.h"
+
+static void sig_signed_message_query(SERVER_REC *server, const char *msg,
+                               const char *nick, const char *address,
+                               int verified)
+{
+       QUERY_REC *query;
+
+       /* create query window if needed */
+       query = privmsg_get_query(server, nick, FALSE, MSGLEVEL_MSGS);
+
+       /* reset the query's last_unread_msg timestamp */
+        if (query != NULL)
+               query->last_unread_msg = time(NULL);
+}
+
+void fe_silc_queries_init(void)
+{
+  signal_add_first("message signed_private",
+                  (SIGNAL_FUNC) sig_signed_message_query);
+}
+
+void fe_silc_queries_deinit(void)
+{
+  signal_remove("message signed_private",
+               (SIGNAL_FUNC) sig_signed_message_query);
+}
diff --git a/apps/irssi/src/fe-common/silc/fe-silc-queries.h b/apps/irssi/src/fe-common/silc/fe-silc-queries.h
new file mode 100644 (file)
index 0000000..c7043c9
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __FE_SILC_QUERIES_H
+#define __FE_SILC_QUERIES_H
+
+void fe_silc_queries_init();
+void fe_silc_queries_deinit();
+
+#endif
diff --git a/apps/irssi/src/fe-common/silc/fe-silcnet.c b/apps/irssi/src/fe-common/silc/fe-silcnet.c
new file mode 100644 (file)
index 0000000..2ab14d3
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ fe-silcnet.c : irssi
+
+    Copyright (C) 2000 Timo Sirainen
+    Copyright (C) 2003 Jochen Eisinger
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "module.h"
+#include "module-formats.h"
+#include "signals.h"
+#include "commands.h"
+#include "levels.h"
+#include "misc.h"
+#include "chatnets.h"
+
+#include "silc-servers.h"
+#include "silc-chatnets.h"
+#include "printtext.h"
+
+static void cmd_silcnet_list(void)
+{
+       GString *str;
+       GSList *tmp;
+
+       str = g_string_new(NULL);
+       printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, SILCTXT_SILCNET_HEADER);
+       for (tmp = chatnets; tmp != NULL; tmp = tmp->next) {
+               SILC_CHATNET_REC *rec = tmp->data;
+
+               if (!IS_SILCNET(rec))
+                        continue;
+
+               g_string_truncate(str, 0);
+               if (rec->nick != NULL)
+                       g_string_sprintfa(str, "nick: %s, ", rec->nick);
+               if (rec->username != NULL)
+                       g_string_sprintfa(str, "username: %s, ", rec->username);
+               if (rec->realname != NULL)
+                       g_string_sprintfa(str, "realname: %s, ", rec->realname);
+               if (rec->own_host != NULL)
+                       g_string_sprintfa(str, "host: %s, ", rec->own_host);
+
+               if (str->len > 1) g_string_truncate(str, str->len-2);
+               printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP,
+                           SILCTXT_SILCNET_LINE, rec->name, str->str);
+       }
+       g_string_free(str, TRUE);
+       printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, SILCTXT_SILCNET_FOOTER);
+}
+
+/* SYNTAX: SILCNET ADD [-nick <nick>] [-user <user>] [-realname <name>]
+                       [-host <host>] <name> */
+static void cmd_silcnet_add(const char *data)
+{
+       GHashTable *optlist;
+       char *name, *value;
+       void *free_arg;
+       SILC_CHATNET_REC *rec;
+
+       if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS,
+                           "silcnet add", &optlist, &name))
+               return;
+       if (*name == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+       rec = silcnet_find(name);
+       if (rec == NULL) {
+               rec = g_new0(SILC_CHATNET_REC, 1);
+               rec->name = g_strdup(name);
+       } else {
+               if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick);
+               if (g_hash_table_lookup(optlist, "user")) g_free_and_null(rec->username);
+               if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname);
+               if (g_hash_table_lookup(optlist, "host")) {
+                       g_free_and_null(rec->own_host);
+                        rec->own_ip4 = rec->own_ip6 = NULL;
+               }
+       }
+
+
+       value = g_hash_table_lookup(optlist, "nick");
+       if (value != NULL && *value != '\0') rec->nick = g_strdup(value);
+       value = g_hash_table_lookup(optlist, "user");
+       if (value != NULL && *value != '\0') rec->username = g_strdup(value);
+       value = g_hash_table_lookup(optlist, "realname");
+       if (value != NULL && *value != '\0') rec->realname = g_strdup(value);
+
+       value = g_hash_table_lookup(optlist, "host");
+       if (value != NULL && *value != '\0') {
+               rec->own_host = g_strdup(value);
+               rec->own_ip4 = rec->own_ip6 = NULL;
+       }
+
+       silcnet_create(rec);
+       printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, SILCTXT_SILCNET_ADDED, name);
+
+       cmd_params_free(free_arg);
+}
+
+/* SYNTAX: SILCNET REMOVE <silcnet> */
+static void cmd_silcnet_remove(const char *data)
+{
+       SILC_CHATNET_REC *rec;
+
+       if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+       rec = silcnet_find(data);
+       if (rec == NULL)
+               printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, SILCTXT_SILCNET_NOT_FOUND, data);
+       else {
+               printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, SILCTXT_SILCNET_REMOVED, data);
+               chatnet_remove(CHATNET(rec));
+       }
+}
+
+static void cmd_silcnet(const char *data, SERVER_REC *server, WI_ITEM_REC *item)
+{
+       if (*data == '\0')
+               cmd_silcnet_list();
+       else
+               command_runsub("silcnet", data, server, item);
+}
+
+void fe_silcnet_init(void)
+{
+       command_bind("silcnet", NULL, (SIGNAL_FUNC) cmd_silcnet);
+       command_bind("silcnet list", NULL, (SIGNAL_FUNC) cmd_silcnet_list);
+       command_bind("silcnet add", NULL, (SIGNAL_FUNC) cmd_silcnet_add);
+       command_bind("silcnet remove", NULL, (SIGNAL_FUNC) cmd_silcnet_remove);
+
+       command_set_options("silcnet add", "-nick -user -realname -host");
+}
+
+void fe_silcnet_deinit(void)
+{
+       command_unbind("silcnet", (SIGNAL_FUNC) cmd_silcnet);
+       command_unbind("silcnet list", (SIGNAL_FUNC) cmd_silcnet_list);
+       command_unbind("silcnet add", (SIGNAL_FUNC) cmd_silcnet_add);
+       command_unbind("silcnet remove", (SIGNAL_FUNC) cmd_silcnet_remove);
+}
diff --git a/apps/irssi/src/fe-common/silc/fe-silcnet.h b/apps/irssi/src/fe-common/silc/fe-silcnet.h
new file mode 100644 (file)
index 0000000..6375eb9
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __FE_SILC_SILCNET_H
+#define __FE_SILC_SILCNET_H
+
+void fe_silcnet_init();
+void fe_silcnet_deinit();
+
+#endif
index 367702286edf0a26d78673a2eb526c0402b0c40a..1892160903a2f79d5ed33a2ff9895beaa794f936 100644 (file)
@@ -33,10 +33,6 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "channel_topic_not_set", "Topic for {channel $0} not set", 1, { 0 } },
        { "cmode", "channel mode/{channel $0} {mode $1} by {nick $2}", 3, { 0, 0, 0 } },
        { "cumode", "channel user mode/{channel $0}/{nick $1} {mode $2} by {nick $3}", 4, { 0, 0, 0, 0 } },
-       { "action", "{action $0-}", 2, { 0, 0 } },
-       { "notice", "{notice $0-}", 2, { 0, 0 } },
-       { "ownaction", "{ownaction $0-}", 2, { 0, 0 } },
-       { "ownnotice", "{ownnotice $0-}", 2, { 0, 0 } },
        { "inviteban_list", "channel {channel $0} $1 list:", 2, { 0, 0 } },
        { "inviteban_string", "$0 - {channel $1}: $2 {ban $3}", 4, { 1, 0, 0, 0 } },
        { "inviteban_pubkey", "$0 - {channel $1}: $2 Fingerprint (SHA1) {ban $3} (Babbleprint (SHA1)  {ban $4})", 5, { 1, 0, 0, 0, 0 } },
@@ -47,7 +43,7 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "kicked", "{nick $0} has been kicked off channel {channel $1} by {nick $2} ($3)", 4, { 0, 0, 0, 0 } },
        { "killed_you", "You have been killed from the SILC Network by {nick $0} ($1)", 2, { 0, 0 } },
        { "killed", "{nick $0} has been killed from the SILC Network by {nick $1} ($2)", 3, { 0, 0, 0 } },
-       { "quieted", "You have been queited and cannot talk on {channel $0}", 1, { 0 } },
+       { "quieted", "You have been quieted and cannot talk on {channel $0}", 1, { 0 } },
        { "appears", "{channick $0} now appears as {channick_hilight $1}", 4, { 0, 0, 0, 0 } },
        { "pubmsg_hilight_signed", "{pubmsghinick_signed $0 $3 $1}$2", 4, { 0, 0, 0, 0 } },
        { "pubmsg_hilight_unknown", "{pubmsghinick_unknown $0 $3 $1}$2", 4, { 0, 0, 0, 0 } },
@@ -82,6 +78,36 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "channel_pk_list", "Channel {channel $0} Public Key List:", 1, { 0 } },
        { "channel_pk_list_entry", "$0 - {channel $1}: $2 $3: Fingerprint (SHA1) {ban $4} (Babbleprint (SHA1) {ban $5})", 6, { 1, 0, 0, 0, 0, 0 } },
        { "channel_pk_no_list", "No Channel Public Key List for {channel $0}", 1, { 0 } },
+       { "own_action", "{ownaction $0}$1", 3, { 0, 0, 0 } },
+       { "own_action_signed", "{ownaction {flag_signed}$0}$1", 3, { 0, 0, 0 } },
+       { "own_action_target", "{ownaction_target $0 $2}$1", 3, { 0, 0, 0 } },
+       { "own_action_target_signed", "{ownaction_target {flag_signed}$0 $2}$1", 3, { 0, 0, 0 } },
+       { "action_public", "{pubaction $0}$2", 3, { 0, 0, 0 } },
+       { "action_public_signed", "{pubaction {flag_signed}$0}$2", 3, { 0, 0, 0 } },
+       { "action_public_unknown", "{pubaction {flag_unknown}$0}$2", 3, { 0, 0, 0 } },
+       { "action_public_failed", "{pubaction {flag_failed}$0}$2", 3, { 0, 0, 0 } },
+       { "action_public_channel", "{pubaction $0{msgchannel $1}}$2", 3, { 0, 0, 0 } },
+       { "action_public_channel_signed", "{pubaction {flag_signed}$0{msgchannel $1}}$2", 3, { 0, 0, 0 } },
+       { "action_public_channel_unknown", "{pubaction {flag_unknown}$0{msgchannel $1}}$2", 3, { 0, 0, 0 } },
+       { "action_public_channel_failed", "{pubaction {flag_failed}$0{msgchannel $1}}$2", 3, { 0, 0, 0 } },
+       { "action_private", "{pvtaction $0}$2", 3, { 0, 0, 0 } },
+       { "action_private_signed", "{pvtaction {flag_signed}$0}$2", 3, { 0, 0, 0 } },
+       { "action_private_unknown", "{pvtaction {flag_unknown}$0}$2", 3, { 0, 0, 0 } },
+       { "action_private_failed", "{pvtaction {flag_failed}$0}$2", 3, { 0, 0, 0 } },
+       { "action_private_query", "{pvtaction_query $0}$2", 3, { 0, 0, 0 } },
+       { "action_private_query_signed", "{pvtaction_query {flag_signed}$0}$2", 3, { 0, 0, 0 } },
+       { "action_private_query_unknown", "{pvtaction_query {flag_unknown}$0}$2", 3, { 0, 0, 0 } },
+       { "action_private_query_failed", "{pvtaction_query {flag_failed}$0}$2", 3, { 0, 0, 0 } },
+       { "own_notice", "{ownnotice notice $0}$1", 2, { 0, 0 } },
+       { "own_notice_signed", "{ownnotice notice {flag_signed}$0}$1", 2, { 0, 0 } },
+       { "notice_public", "{notice $0{pubnotice_channel $1}}$2", 3, { 0, 0, 0 } },
+       { "notice_public_signed", "{notice {flag_signed}$0{pubnotice_channel $1}}$2", 3, { 0, 0, 0 } },
+       { "notice_public_unknown", "{notice {flag_unknown}$0{pubnotice_channel $1}}$2", 3, { 0, 0, 0 } },
+       { "notice_public_failed", "{notice {flag_failed}$0{pubnotice_channel $1}}$2", 3, { 0, 0, 0 } },
+       { "notice_private", "{notice $0{pvtnotice_host $1}}$2", 3, { 0, 0, 0 } },
+       { "notice_private_signed", "{notice {flag_signed}$0{pvtnotice_host $1}}$2", 3, { 0, 0, 0 } },
+       { "notice_private_unknown", "{notice {flag_unknown}$0{pvtnotice_host $1}}$2", 3, { 0, 0, 0 } },
+       { "notice_private_failed", "{notice {flag_failed}$0{pvtnotice_host $1}}$2", 3, { 0, 0, 0 } },
 
        /* WHOIS, WHOWAS and USERS (alias WHO) messages */
        { NULL, "Who Queries", 0 },
@@ -163,6 +189,8 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "watch_nick_change", "Watch: {nick $0} changed nickname to {nick $1}", 2, { 0, 0 } },
        { "message_data", "{nick $0} sent \"{hilight $1}\" data message: cannot display", 2, { 0, 0 } },
        { "stats", "$[25]0: {hilight $1}", 2, { 0, 0 } },
+       { "reattach", "Resuming old session on {hilight $0}, may take a while ...", 1, { 0 } },
+       { "reattach_failed", "Resuming session failed, you may want to remove {hilight $0} before the next connection attempt", 1, { 0 } },
 
        /* File transfer messages */
        { NULL, "FileTransfer", 0 },
@@ -178,7 +206,7 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "file_na", "No file transfers available", 0 },
        { "file_client_na", "No file transfer offered by {nick $0}", 1, { 0 } },
        { "file_show_header", "File transfers", 0 },
-       { "file_show_line", "  $0 $1: $2kB of $3kB ($4%%) - $5kB/s - $6", 7, { 0, 0, 1, 1, 1, 3, 0 } },
+       { "file_show_line", "  $0 [$1] $2: $3kB of $4kB ($5%%) - $6kB/s - $7", 7, { 0, 1, 0, 1, 1, 1, 3, 0 } },
        { "file_already_started", "File transfer already started with {nick $0}", 1, { 0  } },
        { "file_error", "Error during file transfer with {nick $0}", 1, { 0 } },
        { "file_error_no_such_file", "Error during file transfer with {nick $0}: $1: No such file", 2, { 0, 0 } },
@@ -213,6 +241,32 @@ FORMAT_REC fecommon_silc_formats[] = {
        { "attr_extension",            " Extension          : $0", 1, { 0 } },
        { "attr_save", "Would you like to save the attributes (y/n)?", 0 },
        { "attr_saved", "Requested Attributes located in {hilight $0}", 1, { 0 } },
+       /* Public Key Information */
+       { NULL, "Public Key Information", 0},
+
+        { "lstkey_file", "Public key file    : $0", 1, { 0 } },
+        { "lstkey_alg", "Algorithm          : $0", 1, { 0 } },
+        { "lstkey_bits", "Key length (bits)  : $0", 1, { 1 } },
+        { "lstkey_rn", "Real name          : $0", 1, { 0 } },
+        { "lstkey_un", "Username           : $0", 1, { 0 } },
+        { "lstkey_hn", "Hostname           : $0", 1, { 0 } },
+        { "lstkey_email", "Email              : $0", 1, { 0 } },
+        { "lstkey_org", "Organization       : $0", 1, { 0 } },
+        { "lstkey_c", "Country            : $0", 1, { 0 } },
+        { "lstkey_finger", "Fingerprint (SHA1) : $0", 1, { 0 } },
+        { "lstkey_babl", "Babbelprint (SHA1) : $0", 1, { 0 } },
+        { "lstkey_loadpub", "Could not load public key file `$0'", 1, { 0 } },
+       { "lstkey_list", "Stored {hilight $0} public keys:", 1, { 0 } },
+
+       /* Network */
+       { NULL, "Network", 0},
+
+       { "silcnet_added", "SILCNet $0 saved", 1, { 0 } },
+       { "silcnet_removed", "SILCNet $0 removed", 1, { 0 } },
+       { "silcnet_not_found", "SILCNet $0 not found", 1, { 0 } },
+       { "silcnet_header", "%#SILCNets:", 0 },
+       { "silcnet_line", "%#$0: $1", 2, { 0, 0 } },
+       { "silcnet_footer", "", 0 },
 
        { NULL, NULL, 0 }
 };
index f46e6ea2862d7b8e4edbdfc35be8b452de825b22..2c4c064bfe21350e2236c07d8237a91a465368c7 100644 (file)
@@ -30,10 +30,6 @@ enum {
   SILCTXT_CHANNEL_TOPIC_NOT_SET,
   SILCTXT_CHANNEL_CMODE,
   SILCTXT_CHANNEL_CUMODE,
-  SILCTXT_CHANNEL_ACTION,
-  SILCTXT_CHANNEL_NOTICE,
-  SILCTXT_CHANNEL_OWNACTION,
-  SILCTXT_CHANNEL_OWNNOTICE,
   SILCTXT_CHANNEL_INVITEBAN_LIST,
   SILCTXT_CHANNEL_INVITEBAN_STRING,
   SILCTXT_CHANNEL_INVITEBAN_PUBKEY,
@@ -79,6 +75,37 @@ enum {
   SILCTXT_CHANNEL_PK_LIST,
   SILCTXT_CHANNEL_PK_LIST_ENTRY,
   SILCTXT_CHANNEL_PK_NO_LIST,
+  SILCTXT_OWN_ACTION,
+  SILCTXT_OWN_ACTION_SIGNED,
+  SILCTXT_OWN_ACTION_TARGET,
+  SILCTXT_OWN_ACTION_TARGET_SIGNED,
+  SILCTXT_ACTION_PUBLIC,
+  SILCTXT_ACTION_PUBLIC_SIGNED,
+  SILCTXT_ACTION_PUBLIC_UNKNOWN,
+  SILCTXT_ACTION_PUBLIC_FAILED,
+  SILCTXT_ACTION_PUBLIC_CHANNEL,
+  SILCTXT_ACTION_PUBLIC_CHANNEL_SIGNED,
+  SILCTXT_ACTION_PUBLIC_CHANNEL_UNKNOWN,
+  SILCTXT_ACTION_PUBLIC_CHANNEL_FAILED,
+  SILCTXT_ACTION_PRIVATE,
+  SILCTXT_ACTION_PRIVATE_SIGNED,
+  SILCTXT_ACTION_PRIVATE_UNKNOWN,
+  SILCTXT_ACTION_PRIVATE_FAILED,
+  SILCTXT_ACTION_PRIVATE_QUERY,
+  SILCTXT_ACTION_PRIVATE_QUERY_SIGNED,
+  SILCTXT_ACTION_PRIVATE_QUERY_UNKNOWN,
+  SILCTXT_ACTION_PRIVATE_QUERY_FAILED,
+  SILCTXT_OWN_NOTICE,
+  SILCTXT_OWN_NOTICE_SIGNED,
+  SILCTXT_NOTICE_PUBLIC,
+  SILCTXT_NOTICE_PUBLIC_SIGNED,
+  SILCTXT_NOTICE_PUBLIC_UNKNOWN,
+  SILCTXT_NOTICE_PUBLIC_FAILED,
+  SILCTXT_NOTICE_PRIVATE,
+  SILCTXT_NOTICE_PRIVATE_SIGNED,
+  SILCTXT_NOTICE_PRIVATE_UNKNOWN,
+  SILCTXT_NOTICE_PRIVATE_FAILED,
+
 
   SILCTXT_FILL_2,
 
@@ -157,6 +184,8 @@ enum {
   SILCTXT_WATCH_NICK_CHANGE,
   SILCTXT_MESSAGE_DATA,
   SILCTXT_STATS,
+  SILCTXT_REATTACH,
+  SILCTXT_REATTACH_FAILED,
 
   SILCTXT_FILL_5,
 
@@ -205,6 +234,32 @@ enum {
   SILCTXT_ATTR_EXTENSION,
   SILCTXT_ATTR_SAVE,
   SILCTXT_ATTR_SAVED,
+
+  SILCTXT_FILL_7,
+  
+  SILCTXT_LISTKEY_PUB_FILE,
+  SILCTXT_LISTKEY_PUB_ALG,
+  SILCTXT_LISTKEY_PUB_BITS,
+  SILCTXT_LISTKEY_PUB_RN,
+  SILCTXT_LISTKEY_PUB_UN,
+  SILCTXT_LISTKEY_PUB_HN,
+  SILCTXT_LISTKEY_PUB_EMAIL,
+  SILCTXT_LISTKEY_PUB_ORG,
+  SILCTXT_LISTKEY_PUB_C,
+  SILCTXT_LISTKEY_PUB_FINGER,
+  SILCTXT_LISTKEY_PUB_BABL,
+  SILCTXT_LISTKEY_LOADPUB,
+  SILCTXT_LISTKEY_LIST,
+
+  SILCTXT_FILL_8,
+
+  SILCTXT_SILCNET_ADDED,
+  SILCTXT_SILCNET_REMOVED,
+  SILCTXT_SILCNET_NOT_FOUND,
+  SILCTXT_SILCNET_HEADER,
+  SILCTXT_SILCNET_LINE,
+  SILCTXT_SILCNET_FOOTER
+
 };
 
 extern FORMAT_REC fecommon_silc_formats[];
index 10ef1c655542b878d51f5b627002bb0fccd58ee4..ac8fa7e7f47d22d900d1e045216e28e4fcb8f08a 100644 (file)
@@ -4,7 +4,7 @@ include $(top_srcdir)/Makefile.defines.in
 
 moduledir = $(silc_modulesdir)
 
-perl_dirs = common ui textui
+perl_dirs = common ui textui silc
 
 module_LTLIBRARIES = $(perl_module_lib) $(perl_module_fe_lib)
 noinst_LTLIBRARIES = $(perl_static_lib) $(perl_static_fe_lib)
@@ -23,7 +23,7 @@ INCLUDES = \
        -I$(top_srcdir)/src/fe-common/core \
        -I$(top_srcdir)/src/fe-common/silc \
        $(GLIB_CFLAGS) \
-       -DSCRIPTDIR=\""$(libdir)/silc/scripts"\" \
+       -DSCRIPTDIR=\""$(datadir)/silc/scripts"\" \
        -DPERL_USE_LIB=\""$(PERL_USE_LIB)"\" \
        -DPERL_STATIC_LIBS=$(PERL_STATIC_LIBS) \
        $(PERL_CFLAGS)
@@ -113,6 +113,15 @@ textui_sources = \
        textui/typemap \
        textui/module.h
 
+silc_sources = \
+       silc/Silc.xs \
+       silc/Silc.pm \
+       silc/Channel.xs \
+       silc/Server.xs \
+       silc/Query.xs \
+       silc/typemap \
+       silc/module.h
+
 EXTRA_DIST = \
        libperl_dynaloader.la \
        libperl_orig.la \
@@ -120,7 +129,8 @@ EXTRA_DIST = \
        irssi-core.pl \
        $(common_sources) \
        $(ui_sources) \
-       $(textui_sources)
+       $(textui_sources) \
+       $(silc_sources)
 
 all-local:
        for dir in $(perl_dirs); do \
@@ -146,8 +156,8 @@ clean-generic:
 
 distclean-generic:
        for dir in $(perl_dirs); do \
-         cd $$dir; \
-         $(MAKE) realclean; rm -f Makefile.PL; \
+         cd $$dir && \
+         $(MAKE) realclean && rm -f Makefile.PL && \
          cd ..; \
        done
 
diff --git a/apps/irssi/src/perl/silc/Channel.xs b/apps/irssi/src/perl/silc/Channel.xs
new file mode 100644 (file)
index 0000000..5191454
--- /dev/null
@@ -0,0 +1,5 @@
+#include "module.h"
+
+MODULE = Irssi::Silc::Channel  PACKAGE = Irssi::Silc   PREFIX = silc_
+PROTOTYPES: ENABLE
+
diff --git a/apps/irssi/src/perl/silc/Makefile.PL.in b/apps/irssi/src/perl/silc/Makefile.PL.in
new file mode 100644 (file)
index 0000000..7129894
--- /dev/null
@@ -0,0 +1,12 @@
+use ExtUtils::MakeMaker;
+
+sub MY::post_constants {
+       'include @top_srcdir@/Makefile.defines_int';
+}
+
+WriteMakefile('NAME' => 'Irssi::Silc',
+             'LIBS' => '',
+             'OBJECT' => '$(O_FILES)',
+             'TYPEMAPS' => ['../common/typemap'],
+             'INC' => '-I../../.. -I@top_srcdir@/src -I@top_srcdir@/src/core -I@top_srcdir@/src/silc/core -I@top_srcdir@/src/silc -I$(silc_top_srcdir) -I$(silc_top_srcdir)/lib/silccore -I$(silc_top_srcdir)/lib/silccrypt -I$(silc_top_srcdir)/lib/silcmath -I$(silc_top_srcdir)/lib/silcmath/mpi -I$(silc_top_srcdir)/lib/silcske -I$(silc_top_srcdir)/lib/silcsim -I$(silc_top_srcdir)/lib/silcutil -I$(silc_top_srcdir)/lib/silcsftp -I$(silc_top_srcdir)/lib/silcclient -I$(silc_top_srcdir)/lib/contrib -I$(silc_top_srcdir)/includes -I$(silc_top_srcdir)/doc @GLIB_CFLAGS@',
+             'VERSION_FROM' => '@srcdir@/Silc.pm');
diff --git a/apps/irssi/src/perl/silc/Query.xs b/apps/irssi/src/perl/silc/Query.xs
new file mode 100644 (file)
index 0000000..93d30b4
--- /dev/null
@@ -0,0 +1,10 @@
+#include "module.h"
+
+MODULE = Irssi::Silc::Query    PACKAGE = Irssi::Silc::Server   PREFIX = silc_
+PROTOTYPES: ENABLE
+
+Irssi::Silc::Query
+silc_query_create(server_tag, nick, automatic)
+       char *server_tag
+       char *nick
+       int automatic
diff --git a/apps/irssi/src/perl/silc/Server.xs b/apps/irssi/src/perl/silc/Server.xs
new file mode 100644 (file)
index 0000000..fbe45cf
--- /dev/null
@@ -0,0 +1,14 @@
+#include "module.h"
+
+MODULE = Irssi::Silc::Server   PACKAGE = Irssi::Silc::Server   PREFIX = silc_server_
+PROTOTYPES: ENABLE
+
+void
+silc_server_get_channels(server)
+       Irssi::Silc::Server server
+PREINIT:
+       char *ret;
+PPCODE:
+       ret = silc_server_get_channels(server);
+       XPUSHs(sv_2mortal(new_pv(ret)));
+       g_free(ret);
diff --git a/apps/irssi/src/perl/silc/Silc.pm b/apps/irssi/src/perl/silc/Silc.pm
new file mode 100644 (file)
index 0000000..3f6dea6
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# Perl interface to irssi functions.
+#
+
+package Irssi::Silc;
+
+use strict;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
+
+$VERSION = "0.9";
+
+require Exporter;
+require DynaLoader;
+
+@ISA = qw(Exporter DynaLoader);
+@EXPORT = qw();
+@EXPORT_OK = qw();
+
+bootstrap Irssi::Silc $VERSION if (!Irssi::Core::is_static());
+
+Irssi::Silc::init();
+
+Irssi::EXPORT_ALL();
+
+1;
diff --git a/apps/irssi/src/perl/silc/Silc.xs b/apps/irssi/src/perl/silc/Silc.xs
new file mode 100644 (file)
index 0000000..b80f651
--- /dev/null
@@ -0,0 +1,37 @@
+#include "module.h"
+
+static void perl_silc_server_fill_hash(HV *hv, SILC_SERVER_REC *server)
+{
+       perl_server_fill_hash(hv, (SERVER_REC *) server);
+
+       hv_store(hv, "umode", 5, newSViv(server->umode), 0);
+}
+
+MODULE = Irssi::Silc   PACKAGE = Irssi::Silc
+
+PROTOTYPES: ENABLE
+
+void
+init()
+PREINIT:
+       static int initialized = FALSE;
+       int chat_type;
+CODE:
+       if (initialized) return;
+       perl_api_version_check("Irssi::Silc");
+       initialized = TRUE;
+
+       chat_type = chat_protocol_lookup("SILC");
+
+       irssi_add_object(module_get_uniq_id("SERVER", 0),
+                        chat_type, "Irssi::Silc::Server",
+                        (PERL_OBJECT_FUNC) perl_silc_server_fill_hash);
+
+void
+deinit()
+CODE:
+
+BOOT:
+       irssi_boot(Silc__Channel);
+       irssi_boot(Silc__Query);
+       irssi_boot(Silc__Server);
diff --git a/apps/irssi/src/perl/silc/module.h b/apps/irssi/src/perl/silc/module.h
new file mode 100644 (file)
index 0000000..9061ea0
--- /dev/null
@@ -0,0 +1,16 @@
+#include "../common/module.h"
+
+#include "silcincludes.h"
+#include "silcclient.h"
+#include "client_ops.h"
+#include "silc-core.h"
+
+#include "silc-channels.h"
+#include "silc-commands.h"
+#include "silc-queries.h"
+#include "silc-servers.h"
+
+typedef SILC_SERVER_REC *Irssi__Silc__Server;
+typedef SILC_CHANNEL_REC *Irssi__Silc__Channel;
+typedef QUERY_REC *Irssi__Silc__Query;
+typedef NICK_REC *Irssi__Silc__Nick;
diff --git a/apps/irssi/src/perl/silc/typemap b/apps/irssi/src/perl/silc/typemap
new file mode 100644 (file)
index 0000000..2d660e6
--- /dev/null
@@ -0,0 +1,15 @@
+TYPEMAP
+Irssi::Silc::Server            T_IrssiObj
+Irssi::Silc::Channel           T_IrssiObj
+Irssi::Silc::Query             T_IrssiObj
+Irssi::Silc::Nick              T_IrssiObj
+
+INPUT
+
+T_IrssiObj
+       $var = irssi_ref_object($arg)
+
+OUTPUT
+
+T_IrssiObj
+       $arg = iobject_bless((SERVER_REC *)$var);
index 98f3398f0b3c3f717bfdc9b85ee67b8e290132dc..fb35564c7d890d6dc1b00f3a498e8d62bc7a1f36 100644 (file)
@@ -23,7 +23,9 @@ libsilc_core_a_SOURCES = \
        silc-servers.c \
        silc-expandos.c \
        silc-servers-reconnect.c \
-       silc-lag.c
+       silc-lag.c \
+       silc-chatnets.c \
+       silc-cmdqueue.c
 
 noinst_HEADERS = \
        module.h \
@@ -34,5 +36,7 @@ noinst_HEADERS = \
        silc-nicklist.h \
        silc-commands.h \
        silc-queries.h \
-       silc-servers.h 
+       silc-servers.h \
+       silc-chatnets.h \
+       silc-cmdqueue.h
 
index 476fbeda80d86fcaf14452563f78aa176807ef19..44c7b0a32b2c8e6cff34cbeb2c18ff35263f41cc 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 2001 - 2003 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #include "silc-channels.h"
 #include "silc-queries.h"
 #include "silc-nicklist.h"
+#include "silc-cmdqueue.h"
 
 #include "signals.h"
 #include "levels.h"
 #include "settings.h"
 #include "ignore.h"
+#include "special-vars.h"
 #include "fe-common/core/printtext.h"
 #include "fe-common/core/fe-channels.h"
 #include "fe-common/core/keyboard.h"
@@ -49,6 +51,20 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn,
                                SilcSKEPKType pk_type,
                                SilcVerifyPublicKey completion, void *context);
 
+char *silc_get_session_filename(SILC_SERVER_REC *server)
+{
+  char *file, *expanded;
+
+  expanded = parse_special_string(settings_get_str("session_filename"),
+                               SERVER(server), NULL, "", NULL, 0);
+
+  file = silc_calloc(1, strlen(expanded) + 255);
+  snprintf(file, strlen(expanded) + 255, "%s/%s", get_irssi_dir(), expanded);
+  free(expanded);
+
+  return file;
+}
+
 static void silc_get_umode_string(SilcUInt32 mode, char *buf,
                                  SilcUInt32 buf_size)
 {
@@ -83,6 +99,28 @@ static void silc_get_umode_string(SilcUInt32 mode, char *buf,
     strcat(buf, " [blocks invites]");
 }
 
+/* converts an utf-8 string to current locale */
+char * silc_convert_utf8_string(const char *str)
+{
+  int message_len = (str != NULL ? strlen(str) : 0);
+  char *message = silc_calloc(message_len + 1, sizeof(*message));
+
+  g_return_val_if_fail(message != NULL, NULL);
+
+  if (str == NULL) {
+    *message = 0;
+    return message;
+  }
+
+  if (!silc_term_utf8() && silc_utf8_valid(str, message_len))
+    silc_utf8_decode(str, message_len, SILC_STRING_LOCALE,
+                     message, message_len);
+  else
+    strcpy(message, str);
+
+  return message;
+}
+
 /* print "nick appears as" message to every channel of a server */
 static void
 silc_print_nick_change_channel(SILC_SERVER_REC *server, const char *channel,
@@ -290,62 +328,71 @@ int verify_message_signature(SilcClientEntry sender,
 
 char * silc_unescape_data(const char *escaped_data, SilcUInt32 *length)
 {
-  SilcUInt32 ctr, dest=0;
-  char *data;
-
-  data = silc_calloc(strlen(escaped_data), sizeof(char));
-  
-  for (ctr = 0; ctr < strlen(escaped_data); ctr++)
-    if (escaped_data[ctr] == 1)
-      data[dest++] = escaped_data[++ctr] - 1;
-    else
-      data[dest++] = escaped_data[ctr];
+    char *data, *ptr;
+    int i = 0, j = 0, len = strlen(escaped_data);
+
+    data = silc_calloc(len, sizeof(char));
+
+    while (i < len) {
+        ptr = memchr(escaped_data + i, 1, len - i);
+        if (ptr) {
+            int inc = (ptr - escaped_data) - i;
+            memcpy(data + j, escaped_data + i, inc);
+            j += inc;
+            i += inc + 2;
+            data[j++] = *(ptr + 1) - 1;
+        } else {
+            memcpy(data + j, escaped_data + i, len - i);
+            j += (len - i);
+            break;
+        }
+    }
 
-  *length = dest;
-  return data;
+    *length = j;
+    return data;
 }
 
 char * silc_escape_data(const char *data, SilcUInt32 len)
 {
-  char *escaped_data;
-  SilcUInt32 ctr, zeros=0;
-
-  for (ctr = 0; ctr < len; ctr++)
-    if (data[ctr] == 0 || data[ctr] == 1)
-      zeros++;
-
-  escaped_data = silc_calloc(zeros + len, sizeof(char));
-
-  zeros=0;
-  for (ctr = 0; ctr < len; ctr++)
-    switch (data[ctr]) {
-      case 0:
-       escaped_data[zeros++] = 1;
-       escaped_data[zeros++] = 1;
-       break;
-
-      case 1:
-       escaped_data[zeros++] = 1;
-       escaped_data[zeros++] = 2;
-       break;
-
-      default:
-       escaped_data[zeros++] = data[ctr];
-    } 
+    char *escaped_data, *ptr, *ptr0, *ptr1;
+    int i = 0, j = 0;
+
+    escaped_data = silc_calloc(2 * len, sizeof(char));
+
+    while (i < len) {
+        ptr0 = memchr(data + i, 0, len - i);
+        ptr1 = memchr(data + i, 1, len - i);
+
+        ptr = (ptr0 < ptr1 ? (ptr0 ? ptr0 : ptr1) : (ptr1 ? ptr1 : ptr0));
+
+        if (ptr) {
+            int inc = (ptr - data) - i;
+            if (inc)
+                memcpy(escaped_data + j, data + i, inc);
+            j += inc;
+            i += inc;
+            escaped_data[j++] = 1;
+            escaped_data[j++] = *(data + i++) + 1;
+        } else {
+            memcpy(escaped_data + j, data + i, len - i);
+            j += (len - i);
+            break;
+        }
+    }
 
     return escaped_data;
 }
 
-void silc_emit_mime_sig(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
-               const char *data, SilcUInt32 data_len,
-               const char *encoding, const char *type, const char *nick)
+void silc_emit_mime_sig(SILC_SERVER_REC *server, WI_ITEM_REC *item,
+               const char *data, SilcUInt32 data_len, const char *nick,
+              int verified)
 {
    char *escaped_data;
 
    escaped_data = silc_escape_data(data, data_len);
 
-   signal_emit("mime", 6, server, channel, escaped_data, encoding, type, nick);
+   signal_emit("mime", 5, server, item, escaped_data, nick, verified);
+
    silc_free(escaped_data);
 }
 
@@ -356,6 +403,7 @@ void silc_emit_mime_sig(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
 void silc_channel_message(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcChannelEntry channel,
                          SilcMessagePayload payload,
+                         SilcChannelPrivateKey key,
                          SilcMessageFlags flags, const unsigned char *message,
                          SilcUInt32 message_len)
 {
@@ -393,34 +441,15 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
   }
 
   if (flags & SILC_MESSAGE_FLAG_DATA) {
-    /* MIME object received, try to display it as well as we can */
-    char type[128], enc[128];
-    unsigned char *data;
-    SilcUInt32 data_len;
-
-    memset(type, 0, sizeof(type));
-    memset(enc, 0, sizeof(enc));
-    if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
-                        enc, sizeof(enc) - 1, &data, &data_len))
-      return;
-
-    /* Then figure out what we can display */
-    if (strstr(type, "text/") && !strstr(type, "text/t140") &&
-       !strstr(type, "text/vnd")) {
-      /* It is something textual, display it */
-      message = (const unsigned char *)data;
-    } else {
-      silc_emit_mime_sig(server, chanrec, data, data_len,
-               enc, type, nick == NULL ? NULL : nick->nick);
-      message = NULL;
-    }
+    silc_emit_mime_sig(server, (WI_ITEM_REC *)chanrec, message, message_len,
+               nick == NULL ? NULL : nick->nick,
+               flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1);
+    message = NULL;
   }
 
   if (!message)
     return;
 
-  /* FIXME: replace those printformat calls with signals and add signature
-            information to them (if present) */
   if (flags & SILC_MESSAGE_FLAG_ACTION)
     if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
       char tmp[256], *cp, *dm = NULL;
@@ -430,17 +459,22 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
         dm = silc_calloc(message_len + 1, sizeof(*dm));
         cp = dm;
       }
-      silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
+      silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
                        cp, message_len);
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION,
-                         nick == NULL ? "[<unknown>]" : nick->nick, cp);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_action", 6, server, cp, nick->nick,
+                   nick->host, channel->channel_name, verified);
+      else
+        signal_emit("message silc action", 5, server, cp, nick->nick,
+                   nick->host, channel->channel_name);
       silc_free(dm);
     } else {
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_ACTION,
-                         nick == NULL ? "[<unknown>]" : nick->nick,
-                         message);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_action", 6, server, message,
+                   nick->nick, nick->host, channel->channel_name, verified);
+      else
+        signal_emit("message silc action", 5, server, message,
+                   nick->nick, nick->host, channel->channel_name);
     }
   else if (flags & SILC_MESSAGE_FLAG_NOTICE)
     if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
@@ -451,17 +485,22 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
         dm = silc_calloc(message_len + 1, sizeof(*dm));
         cp = dm;
       }
-      silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
+      silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
                        cp, message_len);
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE,
-                         nick == NULL ? "[<unknown>]" : nick->nick, cp);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+       signal_emit("message silc signed_notice", 6, server, cp, nick->nick,
+               nick->host, channel->channel_name, verified);
+      else
+       signal_emit("message silc notice", 5, server, cp, nick->nick,
+               nick->host, channel->channel_name);
       silc_free(dm);
     } else {
-      printformat_module("fe-common/silc", server, channel->channel_name,
-                         MSGLEVEL_NOTICES, SILCTXT_CHANNEL_NOTICE,
-                         nick == NULL ? "[<unknown>]" : nick->nick,
-                         message);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+       signal_emit("message silc signed_notice", 6, server, message,
+               nick->nick, nick->host, channel->channel_name, verified);
+      else
+       signal_emit("message silc notice", 5, server, message,
+               nick->nick, nick->host, channel->channel_name);
     }
   else {
     if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
@@ -474,7 +513,7 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn,
        cp = dm;
       }
 
-      silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
+      silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
                       cp, message_len);
       if (flags & SILC_MESSAGE_FLAG_SIGNED)
         signal_emit("message signed_public", 6, server, cp,
@@ -535,65 +574,117 @@ void silc_private_message(SilcClient client, SilcClientConnection conn,
   }
 
   if (flags & SILC_MESSAGE_FLAG_DATA) {
-    /* MIME object received, try to display it as well as we can */
-    char type[128], enc[128];
-    unsigned char *data;
-    SilcUInt32 data_len;
-
-    memset(type, 0, sizeof(type));
-    memset(enc, 0, sizeof(enc));
-    if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
-                        enc, sizeof(enc) - 1, &data, &data_len))
-      return;
-
-    /* Then figure out what we can display */
-    if (strstr(type, "text/") && !strstr(type, "text/t140") &&
-       !strstr(type, "text/vnd")) {
-      /* It is something textual, display it */
-      message = (const unsigned char *)data;
-    } else {
-      silc_emit_mime_sig(server, NULL, data, data_len,
-                       enc, type, sender->nickname ? sender->nickname :
-                                  "[<unknown>]");
-      message = NULL;
-    }
+    silc_emit_mime_sig(server,
+               sender->nickname ?
+               (WI_ITEM_REC *)query_find(SERVER(server), sender->nickname) :
+               NULL,
+               message, message_len,
+               sender->nickname ? sender->nickname : "[<unknown>]",
+               flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1);
+    message = NULL;
   }
 
   if (!message)
     return;
 
-  if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
-    char tmp[256], *cp, *dm = NULL;
+  if (flags & SILC_MESSAGE_FLAG_ACTION)
+    if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
+      char tmp[256], *cp, *dm = NULL;
+      memset(tmp, 0, sizeof(tmp));
+      cp = tmp;
+      if(message_len > sizeof(tmp) - 1) {
+        dm = silc_calloc(message_len + 1, sizeof(*dm));
+        cp = dm;
+      }
+      silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
+                       cp, message_len);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_private_action", 6, server, cp,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL,
+                   NULL, verified);
+      else
+        signal_emit("message silc private_action", 5, server, cp,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL, NULL);
+      silc_free(dm);
+    } else {
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_private_action", 6, server, message,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL,
+                   NULL, verified);
+      else
+        signal_emit("message silc private_action", 5, server, message,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL, NULL);
+    }
+  else if (flags & SILC_MESSAGE_FLAG_NOTICE)
+    if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
+      char tmp[256], *cp, *dm = NULL;
+      memset(tmp, 0, sizeof(tmp));
+      cp = tmp;
+      if(message_len > sizeof(tmp) - 1) {
+        dm = silc_calloc(message_len + 1, sizeof(*dm));
+        cp = dm;
+      }
+      silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
+                       cp, message_len);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_private_notice", 6, server, cp,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL,
+                   NULL, verified);
+      else
+        signal_emit("message silc private_notice", 5, server, cp,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL, NULL);
+      silc_free(dm);
+    } else {
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message silc signed_private_notice", 6, server, message,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL,
+                   NULL, verified);
+      else
+        signal_emit("message silc private_notice", 5, server, message,
+                   sender->nickname ? sender->nickname : "[<unknown>]",
+                   sender->username ? userhost : NULL, NULL);
+    }
+  else {
+    if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) {
+      char tmp[256], *cp, *dm = NULL;
+
+      memset(tmp, 0, sizeof(tmp));
+      cp = tmp;
+      if (message_len > sizeof(tmp) - 1) {
+        dm = silc_calloc(message_len + 1, sizeof(*dm));
+        cp = dm;
+      }
 
-    memset(tmp, 0, sizeof(tmp));
-    cp = tmp;
-    if (message_len > sizeof(tmp) - 1) {
-      dm = silc_calloc(message_len + 1, sizeof(*dm));
-      cp = dm;
+      silc_utf8_decode(message, message_len, SILC_STRING_LOCALE,
+                    cp, message_len);
+      if (flags & SILC_MESSAGE_FLAG_SIGNED)
+        signal_emit("message signed_private", 5, server, cp,
+                 sender->nickname ? sender->nickname : "[<unknown>]",
+                 sender->username ? userhost : NULL, verified);
+      else
+        signal_emit("message private", 4, server, cp,
+                 sender->nickname ? sender->nickname : "[<unknown>]",
+                 sender->username ? userhost : NULL);
+      silc_free(dm);
+      return;
     }
 
-    silc_utf8_decode(message, message_len, SILC_STRING_LANGUAGE,
-                    cp, message_len);
     if (flags & SILC_MESSAGE_FLAG_SIGNED)
-      signal_emit("message signed_private", 5, server, cp,
-                 sender->nickname ? sender->nickname : "[<unknown>]",
-                 sender->username ? userhost : NULL, verified);
+      signal_emit("message signed_private", 5, server, message,
+              sender->nickname ? sender->nickname : "[<unknown>]",
+              sender->username ? userhost : NULL, verified);
     else
-      signal_emit("message private", 4, server, cp,
-                 sender->nickname ? sender->nickname : "[<unknown>]",
-                 sender->username ? userhost : NULL);
-    silc_free(dm);
-    return;
+      signal_emit("message private", 4, server, message,
+              sender->nickname ? sender->nickname : "[<unknown>]",
+              sender->username ? userhost : NULL);
   }
-
-  if (flags & SILC_MESSAGE_FLAG_SIGNED)
-    signal_emit("message signed_private", 5, server, message,
-               sender->nickname ? sender->nickname : "[<unknown>]",
-               sender->username ? userhost : NULL, verified);
-  else
-    signal_emit("message private", 4, server, message,
-               sender->nickname ? sender->nickname : "[<unknown>]",
-               sender->username ? userhost : NULL);
 }
 
 /* Notify message to the client. The notify arguments are sent in the
@@ -1201,6 +1292,9 @@ void silc_connect(SilcClient client, SilcClientConnection conn,
   switch (status) {
   case SILC_CLIENT_CONN_SUCCESS:
     /* We have successfully connected to server */
+    if ((client->nickname != NULL) &&
+        (strcmp(client->nickname, client->username)))
+      silc_queue_enable(conn); /* enable queueing until we have our nick */
     server->connected = TRUE;
     signal_emit("event connected", 1, server);
     break;
@@ -1222,14 +1316,37 @@ void silc_connect(SilcClient client, SilcClientConnection conn,
       signal_emit("message own_nick", 4, server, server->nick, old, "");
       g_free(old);
     }
+
+    /* remove the detach data now */
+    {
+      char *file;
+
+      file = silc_get_session_filename(server);
+
+      unlink(file);
+      silc_free(file);
+    }
     break;
 
   default:
-    server->connection_lost = TRUE;
-    if (server->conn)
-      server->conn->context = NULL;
-    server_disconnect(SERVER(server));
-    break;
+    {
+      char * file;
+
+      file = silc_get_session_filename(server);
+
+      if (silc_file_size(file) > 0)
+        printformat_module("fe-common/silc", server, NULL,
+                          MSGLEVEL_CRAP, SILCTXT_REATTACH_FAILED, file);
+
+      silc_free(file);
+
+      server->connection_lost = TRUE;
+      if (server->conn)
+        server->conn->context = NULL;
+      server_disconnect(SERVER(server));
+
+      break;
+    }
   }
 }
 
@@ -1578,7 +1695,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        /* Print the unknown nick for user */
        unsigned char *tmp =
          silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                    3, NULL);
+                                    2, NULL);
        if (tmp)
          silc_say_error("%s: %s", tmp,
                         silc_get_status_message(status));
@@ -1696,7 +1813,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        /* Print the unknown nick for user */
        unsigned char *tmp =
          silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                    3, NULL);
+                                    2, NULL);
        if (tmp)
          silc_say_error("%s: %s", tmp,
                         silc_get_status_message(status));
@@ -1730,11 +1847,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
     {
       char *nickname, *username, *realname;
 
-      if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
-         status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
-       char *tmp;
-       tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
-                                        3, NULL);
+      if (status == SILC_STATUS_ERR_NO_SUCH_NICK) {
+       char *tmp =
+         silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
+                                    2, NULL);
        if (tmp)
          silc_say_error("%s: %s", tmp,
                         silc_get_status_message(status));
@@ -1820,7 +1936,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
            cp = dm;
          }
 
-         silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE,
+         silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE,
                           cp, strlen(topic));
          topic = cp;
        }
@@ -1872,17 +1988,22 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        collider = silc_client_get_client_by_id(client, conn,
                                                old->id);
 
-        memset(buf, 0, sizeof(buf));
-        snprintf(buf, sizeof(buf) - 1, "%s@%s",
-                collider->username, collider->hostname);
-       nicklist_rename_unique(SERVER(server),
-                              old, old->nickname,
-                              collider, collider->nickname);
-       silc_print_nick_change(server, collider->nickname,
-                              client_entry->nickname, buf);
-       g_slist_free(nicks);
+       if (collider != client_entry) {
+
+          memset(buf, 0, sizeof(buf));
+          snprintf(buf, sizeof(buf) - 1, "%s@%s",
+                  collider->username, collider->hostname);
+         nicklist_rename_unique(SERVER(server),
+                                old, old->nickname,
+                                collider, collider->nickname);
+         silc_print_nick_change(server, collider->nickname,
+                                client_entry->nickname, buf);
+       }
       }
 
+      if (nicks != NULL)
+       g_slist_free(nicks);
+
       old = g_strdup(server->nick);
       server_change_nick(SERVER(server), client_entry->nickname);
       nicklist_rename_unique(SERVER(server),
@@ -1890,6 +2011,11 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
                             client_entry, client_entry->nickname);
       signal_emit("message own_nick", 4, server, server->nick, old, "");
       g_free(old);
+
+      /* when connecting to a server, the last thing we receive
+         is a SILC_COMMAND_LIST reply. Since we enable queueing
+        during the connection, we can now safely disable it again */
+      silc_queue_disable(conn);
       break;
     }
 
@@ -1905,6 +2031,8 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
 
       (void)va_arg(vp, SilcChannelEntry);
       name = va_arg(vp, char *);
+      if (!name)
+       return;
       topic = va_arg(vp, char *);
       usercount = va_arg(vp, int);
 
@@ -1917,7 +2045,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
          cp = dm;
        }
 
-       silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE,
+       silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE,
                         cp, strlen(topic));
        topic = cp;
       }
@@ -2169,7 +2297,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
          cp = dm;
        }
 
-       silc_utf8_decode(topic, strlen(topic), SILC_STRING_LANGUAGE,
+       silc_utf8_decode(topic, strlen(topic), SILC_STRING_LOCALE,
                         cp, strlen(topic));
        topic = cp;
       }
@@ -2340,11 +2468,19 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
 
       /* Print the channel public key list */
       if (channel_pubkeys)
-       silc_parse_channel_public_keys(server, channel_entry, channel_pubkeys);
+        silc_parse_channel_public_keys(server, channel_entry, channel_pubkeys);
       else
-       printformat_module("fe-common/silc", server, NULL,
-                          MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST,
-                          channel_entry->channel_name);
+        printformat_module("fe-common/silc", server, NULL,
+                         MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST,
+                         channel_entry->channel_name);
+
+    }
+    break;
+
+  case SILC_COMMAND_LEAVE:
+    {
+      /* we might be cycling, so disable queueing again */
+      silc_queue_disable(conn);
     }
     break;
 
@@ -2884,13 +3020,14 @@ void
 silc_detach(SilcClient client, SilcClientConnection conn,
             const unsigned char *detach_data, SilcUInt32 detach_data_len)
 {
-  char file[256];
+  SILC_SERVER_REC *server = conn->context;
+  char *file;
 
   /* Save the detachment data to file. */
 
-  memset(file, 0, sizeof(file));
-  snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir());
+  file = silc_get_session_filename(server);
   silc_file_writefile(file, detach_data, detach_data_len);
+  silc_free(file);
 }
 
 
index 31f5ad2989bc03af515ee948be049a5af09ec0eb..d9c181822a50034fa1731a333c3a4d07ff2ecaf0 100644 (file)
@@ -10,7 +10,7 @@
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, 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
 #ifndef CLIENT_OPS_H
 #define CLIENT_OPS_H
 
-void silc_say(SilcClient client, SilcClientConnection conn, 
+#include "silc-servers.h"
+
+void silc_say(SilcClient client, SilcClientConnection conn,
              SilcClientMessageType type, char *msg, ...);
 void silc_say_error(char *msg, ...);
 void silc_channel_message(SilcClient client, SilcClientConnection conn,
-                         SilcClientEntry sender, 
-                         SilcChannelEntry channel, 
+                         SilcClientEntry sender,
+                         SilcChannelEntry channel,
                          SilcMessagePayload payload,
-                         SilcMessageFlags flags, 
+                         SilcChannelPrivateKey key,
+                         SilcMessageFlags flags,
                          const unsigned char *message,
                          SilcUInt32 message_len);
 void silc_private_message(SilcClient client, SilcClientConnection conn,
-                         SilcClientEntry sender, 
+                         SilcClientEntry sender,
                          SilcMessagePayload payload,
-                         SilcMessageFlags flags, 
+                         SilcMessageFlags flags,
                          const unsigned char *message,
                          SilcUInt32 message_len);
-void silc_notify(SilcClient client, SilcClientConnection conn, 
+void silc_notify(SilcClient client, SilcClientConnection conn,
                 SilcNotifyType type, ...);
-void silc_command(SilcClient client, SilcClientConnection conn, 
+void silc_command(SilcClient client, SilcClientConnection conn,
                  SilcClientCommandContext cmd_context, bool success,
                  SilcCommand command, SilcStatus status);
 void silc_command_reply(SilcClient client, SilcClientConnection conn,
@@ -52,13 +55,13 @@ void silc_disconnect(SilcClient client, SilcClientConnection conn,
 void silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
                         SilcAskPassphrase completion, void *context);
 void silc_verify_public_key(SilcClient client, SilcClientConnection conn,
-                           SilcSocketType conn_type, unsigned char *pk, 
+                           SilcSocketType conn_type, unsigned char *pk,
                            SilcUInt32 pk_len, SilcSKEPKType pk_type,
                            SilcVerifyPublicKey completion, void *context);
 void silc_get_auth_method(SilcClient client, SilcClientConnection conn,
                          char *hostname, SilcUInt16 port,
                          SilcGetAuthMeth completion, void *context);
-void silc_failure(SilcClient client, SilcClientConnection conn, 
+void silc_failure(SilcClient client, SilcClientConnection conn,
                  SilcProtocol protocol, void *failure);
 bool silc_key_agreement(SilcClient client, SilcClientConnection conn,
                        SilcClientEntry client_entry, const char *hostname,
@@ -72,7 +75,10 @@ silc_detach(SilcClient client, SilcClientConnection conn,
             const unsigned char *detach_data, SilcUInt32 detach_data_len);
 char *
 silc_unescape_data(const char *escaped_data, SilcUInt32 *length);
-char * 
+char *
 silc_escape_data(const char *data, SilcUInt32 len);
 
+char *
+silc_get_session_filename(SILC_SERVER_REC *server);
+
 #endif
index 8f1639329813e77636874510c9b35420ee2eca08..7118e5ccaf086509f2746eb3765abe064028dae4 100644 (file)
@@ -83,9 +83,8 @@ void silc_client_list_pkcs()
 /* This checks stats for various SILC files and directories. First it 
    checks if ~/.silc directory exist and is owned by the correct user. If 
    it doesn't exist, it will create the directory. After that it checks if
-   user's Public and Private key files exists and that they aren't expired.
-   If they doesn't exist or they are expired, they will be (re)created
-   after return. */
+   user's Public and Private key files exists. If they doesn't exist they 
+   will be created after return. */
 
 int silc_client_check_silc_dir()
 {
@@ -93,7 +92,6 @@ int silc_client_check_silc_dir()
   char servfilename[256], clientfilename[256], friendsfilename[256];
   struct stat st;
   struct passwd *pw;
-  time_t curtime, modtime;
 
   SILC_LOG_DEBUG(("Checking ~./silc directory"));
 
@@ -288,49 +286,6 @@ int silc_client_check_silc_dir()
     fprintf(stderr, "Done.\n\n");
   }
 
-  /* See if the key has expired. */
-  modtime = st.st_mtime;       /* last modified */
-  curtime = time(0) - modtime;
-    
-  /* 86400 is seconds in a day. */
-  if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
-    char *answer;
-
-    fprintf(stdout, 
-           "----------------------------------------------------\n"
-           "Your private key has expired and needs to be\n" 
-           "recreated.  Would you like to create a new key pair\n"
-           "now?  If you answer Yes, the new key will expire in\n"
-           "%d days from today.  If you answer No, the old key\n"
-           "will expire again in %d days from today.\n"
-           "----------------------------------------------------\n",
-           SILC_CLIENT_KEY_EXPIRES, SILC_CLIENT_KEY_EXPIRES);
-
-    answer = silc_get_input("Would you like to create a new key pair "
-                           "(y/n)?: ", FALSE);
-    while (!answer) {
-      printf("Answer 'y' or 'n' and press Enter\n");
-      answer = silc_get_input("Would you like to create a new key pair "
-                             "(y/n)?: ", FALSE);
-    }
-    if (answer[0] == 'Y' || answer[0] == 'y') {
-      silc_create_key_pair(SILC_CLIENT_DEF_PKCS,
-                          SILC_CLIENT_DEF_PKCS_LEN,
-                          file_public_key, file_private_key, NULL,
-                          NULL, NULL, NULL, NULL, FALSE);
-      printf("Press <Enter> to continue...\n");
-      getchar();
-    } else {
-#ifdef HAVE_UTIME
-      struct utimbuf utim;
-      utim.actime = time(NULL);
-      utim.modtime = time(NULL);
-      utime(file_private_key, &utim);
-#endif
-    }
-    silc_free(answer);
-  }
-  
   return TRUE;
 }
 
index 2ebdcc7ab42de108834ae6b9405a080ad8b704ba..9c8028b56393a761eeb467bd84688cecc5b3c090 100644 (file)
@@ -1,19 +1,19 @@
 /*
   silc-channels.c : irssi
 
-  Copyright (C) 2000 - 2001 Timo Sirainen
+  Copyright (C) 2000 - 2001, 2004 Timo Sirainen
                             Pekka Riikonen <priikone@poseidon.pspt.fi>
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
-  
+
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
@@ -38,6 +38,7 @@
 #include "silc-channels.h"
 #include "silc-queries.h"
 #include "silc-nicklist.h"
+#include "silc-cmdqueue.h"
 #include "window-item-def.h"
 
 #include "fe-common/core/printtext.h"
 #include "silc-commands.h"
 
 void sig_mime(SILC_SERVER_REC *server, SILC_CHANNEL_REC *channel,
-               const char *blob, const char *enc, const char *type,
-               const char *nick)
+               const char *blob, const char *nick, int verified)
 {
+  char type[128], enc[128];
+  unsigned char *data, *message;
+  SilcUInt32 data_len, message_len;
 
   if (!(IS_SILC_SERVER(server)))
     return;
-  
-  printformat_module("fe-common/silc", server, 
-                        channel == NULL ? NULL : channel->name,
-                        MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
-                        nick == NULL ? "[<unknown>]" : nick, type);
+
+  message = silc_unescape_data(blob, &message_len);
+
+  memset(type, 0, sizeof(type));
+  memset(enc, 0, sizeof(enc));
+
+  if (!silc_mime_parse(message, message_len, NULL, 0, type, sizeof(type) - 1,
+                enc, sizeof(enc) - 1, &data, &data_len)) {
+    silc_free(message);
+    return;
+  }
+
+  printformat_module("fe-common/silc", server,
+                      channel == NULL ? NULL : channel->name,
+                      MSGLEVEL_CRAP, SILCTXT_MESSAGE_DATA,
+                      nick == NULL ? "[<unknown>]" : nick, type);
+
+  silc_free(message);
 
 }
 
@@ -88,6 +104,8 @@ static void sig_channel_destroyed(SILC_CHANNEL_REC *channel)
     /* destroying channel record without actually
        having left the channel yet */
     silc_command_exec(channel->server, "LEAVE", channel->name);
+    /* enable queueing because we destroy the channel immedially */
+    silc_queue_enable(channel->server->conn);
   }
 }
 
@@ -155,7 +173,7 @@ static void command_part(const char *data, SILC_SERVER_REC *server,
 {
   SILC_CHANNEL_REC *chanrec;
   char userhost[256];
-  
+
   CMD_SILC_SERVER(server);
 
   if (!IS_SILC_SERVER(server) || !server->connected)
@@ -168,147 +186,128 @@ static void command_part(const char *data, SILC_SERVER_REC *server,
   }
 
   chanrec = silc_channel_find(server, data);
-  if (chanrec == NULL) 
+  if (chanrec == NULL)
     cmd_return_error(CMDERR_CHAN_NOT_FOUND);
 
   memset(userhost, 0, sizeof(userhost));
   snprintf(userhost, sizeof(userhost) - 1, "%s@%s",
-          server->conn->local_entry->username, 
+          server->conn->local_entry->username,
           server->conn->local_entry->hostname);
   signal_emit("message part", 5, server, chanrec->name,
              server->nick, userhost, "");
-  
+
   chanrec->left = TRUE;
   silc_command_exec(server, "LEAVE", chanrec->name);
+  /* enable queueing because we destroy the channel immedially */
+  silc_queue_enable(server->conn);
   signal_stop();
 
   channel_destroy(CHANNEL(chanrec));
 }
 
-/* ME local command. */
 
-static void command_me(const char *data, SILC_SERVER_REC *server,
-                      WI_ITEM_REC *item)
+/* ACTION local command. */
+
+static void command_action(const char *data, SILC_SERVER_REC *server,
+                          WI_ITEM_REC *item)
 {
-  SILC_CHANNEL_REC *chanrec;
-  char *tmpcmd = "ME", *tmp;
-  SilcUInt32 argc = 0;
-  unsigned char *message = NULL;
-  unsigned char **argv;
-  SilcUInt32 *argv_lens, *argv_types;
-  int i;
-  CMD_SILC_SERVER(server);
+  GHashTable *optlist;
+  char *target, *msg;
+  char *message = NULL;
+  int target_type;
+  void *free_arg;
 
+  CMD_SILC_SERVER(server);
   if (!IS_SILC_SERVER(server) || !server->connected)
     cmd_return_error(CMDERR_NOT_CONNECTED);
 
-  if (!IS_SILC_CHANNEL(item))
+  if ((item != NULL) && (!IS_SILC_CHANNEL(item) && !IS_SILC_QUERY(item)))
     cmd_return_error(CMDERR_NOT_JOINED);
 
   /* Now parse all arguments */
-  tmp = g_strconcat(tmpcmd, " ", data, NULL);
-  silc_parse_command_line(tmp, &argv, &argv_lens,
-                         &argv_types, &argc, 2);
-  g_free(tmp);
-
-  if (argc < 2)
-    cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+  if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
+                     PARAM_FLAG_GETREST,
+                     "action", &optlist, &target, &msg))
+    return;
 
-  chanrec = silc_channel_find(server, item->visible_name);
-  if (chanrec == NULL) 
-    cmd_return_error(CMDERR_CHAN_NOT_FOUND);
+  if (*target == '\0' || *msg == '\0')
+    cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+  if (strcmp(target, "*") == 0) {
+    /* send to active channel/query */
+    if (item == NULL)
+      cmd_param_error(CMDERR_NOT_JOINED);
+
+    target_type = IS_SILC_CHANNEL(item) ?
+           SEND_TARGET_CHANNEL : SEND_TARGET_NICK;
+    target = (char *)window_item_get_target(item);
+  } else if (g_hash_table_lookup(optlist, "channel") != NULL)
+    target_type = SEND_TARGET_CHANNEL;
+  else {
+    target_type = SEND_TARGET_NICK;
+  }
 
   if (!silc_term_utf8()) {
-    int len = silc_utf8_encoded_len(argv[1], argv_lens[1],
-                                   SILC_STRING_LANGUAGE);
+    int len = silc_utf8_encoded_len(msg, strlen(msg),
+                                   SILC_STRING_LOCALE);
     message = silc_calloc(len + 1, sizeof(*message));
     g_return_if_fail(message != NULL);
-    silc_utf8_encode(argv[1], argv_lens[1], SILC_STRING_LANGUAGE,
+    silc_utf8_encode(msg, strlen(msg), SILC_STRING_LOCALE,
                     message, len);
   }
 
-  /* Send the action message */
-  silc_client_send_channel_message(silc_client, server->conn, 
-                                  chanrec->entry, NULL,
-                                  SILC_MESSAGE_FLAG_ACTION |
-                                  SILC_MESSAGE_FLAG_UTF8,
-                                  message ? message : argv[1],
-                                  message ? strlen(message) : argv_lens[1],
-                                  TRUE);
-
-  printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
-                    MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION, 
-                     server->conn->local_entry->nickname, argv[1]);
-
-  for (i = 0; i < argc; i++)
-    silc_free(argv[i]);
-  silc_free(argv_lens);
-  silc_free(argv_types);
+  if (target != NULL) {
+    if (target_type == SEND_TARGET_CHANNEL) {
+      if (silc_send_channel(server, target, (message != NULL ? message : msg),
+                           SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 |
+                           (g_hash_table_lookup(optlist, "sign") != NULL ?
+                            SILC_MESSAGE_FLAG_SIGNED : 0))) {
+       if (g_hash_table_lookup(optlist, "sign"))
+          signal_emit("message silc signed_own_action", 3, server, msg, target);
+       else
+          signal_emit("message silc own_action", 3, server, msg, target);
+      }
+    } else {
+      if (silc_send_msg(server, target, (message != NULL ? message : msg),
+                       (message != NULL ? strlen(message) : strlen(msg)),
+                       SILC_MESSAGE_FLAG_ACTION | SILC_MESSAGE_FLAG_UTF8 |
+                       (g_hash_table_lookup(optlist, "sign") != NULL ?
+                        SILC_MESSAGE_FLAG_SIGNED : 0))) {
+       if (g_hash_table_lookup(optlist, "sign"))
+         signal_emit("message silc signed_own_private_action", 3,
+                         server, msg, target);
+       else
+         signal_emit("message silc own_private_action", 3,
+                         server, msg, target);
+      }
+    }
+  }
+
+  cmd_params_free(free_arg);
   silc_free(message);
 }
 
-/* ACTION local command. Same as ME but takes the channel as mandatory
-   argument. */
+/* ME local command. */
 
-static void command_action(const char *data, SILC_SERVER_REC *server,
-                          WI_ITEM_REC *item)
+static void command_me(const char *data, SILC_SERVER_REC *server,
+                      WI_ITEM_REC *item)
 {
-  SILC_CHANNEL_REC *chanrec;
-  char *tmpcmd = "ME", *tmp;
-  SilcUInt32 argc = 0;
-  unsigned char *message = NULL;
-  unsigned char **argv;
-  SilcUInt32 *argv_lens, *argv_types;
-  int i;
+  char *tmpcmd;
+
   CMD_SILC_SERVER(server);
   if (!IS_SILC_SERVER(server) || !server->connected)
     cmd_return_error(CMDERR_NOT_CONNECTED);
 
-  if (!IS_SILC_CHANNEL(item))
+  if (!IS_SILC_CHANNEL(item) && !IS_SILC_QUERY(item))
     cmd_return_error(CMDERR_NOT_JOINED);
 
-  /* Now parse all arguments */
-  tmp = g_strconcat(tmpcmd, " ", data, NULL);
-  silc_parse_command_line(tmp, &argv, &argv_lens,
-                         &argv_types, &argc, 3);
-  g_free(tmp);
-
-  if (argc < 3)
-    cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
-
-  chanrec = silc_channel_find(server, argv[1]);
-  if (chanrec == NULL) 
-    cmd_return_error(CMDERR_CHAN_NOT_FOUND);
+  if (IS_SILC_CHANNEL(item))
+    tmpcmd = g_strdup_printf("-channel %s %s", item->visible_name, data);
+  else
+    tmpcmd = g_strdup_printf("%s %s", item->visible_name, data);
 
-  if (!silc_term_utf8()) {
-    int len = silc_utf8_encoded_len(argv[2], argv_lens[2],
-                                   SILC_STRING_LANGUAGE);
-    message = silc_calloc(len + 1, sizeof(*message));
-    g_return_if_fail(message != NULL);
-    silc_utf8_encode(argv[2], argv_lens[2], SILC_STRING_LANGUAGE,
-                    message, len);
-  }
-
-  /* Send the action message */
-  silc_client_send_channel_message(silc_client, server->conn, 
-                                  chanrec->entry, NULL,
-                                  SILC_MESSAGE_FLAG_ACTION |
-                                  SILC_MESSAGE_FLAG_UTF8,
-                                  message ? message : argv[2],
-                                  message ? strlen(message) : argv_lens[2],
-                                  TRUE);
-
-  printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
-                    MSGLEVEL_ACTIONS, SILCTXT_CHANNEL_OWNACTION, 
-                     server->conn->local_entry->nickname, argv[2]);
-
-  for (i = 0; i < argc; i++)
-    silc_free(argv[i]);
-  silc_free(argv_lens);
-  silc_free(argv_types);
-  silc_free(message);
+  command_action(tmpcmd, server, item);
+  g_free(tmpcmd);
 }
 
 /* NOTICE local command. */
@@ -316,60 +315,79 @@ static void command_action(const char *data, SILC_SERVER_REC *server,
 static void command_notice(const char *data, SILC_SERVER_REC *server,
                           WI_ITEM_REC *item)
 {
-  SILC_CHANNEL_REC *chanrec;
-  char *tmpcmd = "ME", *tmp;
-  SilcUInt32 argc = 0;
-  unsigned char *message = NULL;
-  unsigned char **argv;
-  SilcUInt32 *argv_lens, *argv_types;
-  int i;
+  GHashTable *optlist;
+  char *target, *msg;
+  char *message = NULL;
+  int target_type;
+  void *free_arg;
+
   CMD_SILC_SERVER(server);
   if (!IS_SILC_SERVER(server) || !server->connected)
     cmd_return_error(CMDERR_NOT_CONNECTED);
 
-  if (!IS_SILC_CHANNEL(item))
+  if ((item != NULL) && (!IS_SILC_CHANNEL(item) && !IS_SILC_QUERY(item)))
     cmd_return_error(CMDERR_NOT_JOINED);
 
   /* Now parse all arguments */
-  tmp = g_strconcat(tmpcmd, " ", data, NULL);
-  silc_parse_command_line(tmp, &argv, &argv_lens,
-                         &argv_types, &argc, 2);
-  g_free(tmp);
-
-  if (argc < 2)
-    cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
+  if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTIONS |
+                     PARAM_FLAG_GETREST,
+                     "notice", &optlist, &target, &msg))
+    return;
 
-  chanrec = silc_channel_find(server, item->visible_name);
-  if (chanrec == NULL) 
-    cmd_return_error(CMDERR_CHAN_NOT_FOUND);
+  if (*target == '\0' || *msg == '\0')
+    cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS);
+
+  if (strcmp(target, "*") == 0) {
+    /* send to active channel/query */
+    if (item == NULL)
+      cmd_param_error(CMDERR_NOT_JOINED);
+
+    target_type = IS_SILC_CHANNEL(item) ?
+           SEND_TARGET_CHANNEL : SEND_TARGET_NICK;
+    target = (char *)window_item_get_target(item);
+  } else if (g_hash_table_lookup(optlist, "channel") != NULL)
+    target_type = SEND_TARGET_CHANNEL;
+  else {
+    target_type = SEND_TARGET_NICK;
+  }
 
   if (!silc_term_utf8()) {
-    int len = silc_utf8_encoded_len(argv[1], argv_lens[1],
-                                   SILC_STRING_LANGUAGE);
+    int len = silc_utf8_encoded_len(msg, strlen(msg),
+                                   SILC_STRING_LOCALE);
     message = silc_calloc(len + 1, sizeof(*message));
     g_return_if_fail(message != NULL);
-    silc_utf8_encode(argv[1], argv_lens[1], SILC_STRING_LANGUAGE,
+    silc_utf8_encode(msg, strlen(msg), SILC_STRING_LOCALE,
                     message, len);
   }
 
-  /* Send the action message */
-  silc_client_send_channel_message(silc_client, server->conn, 
-                                  chanrec->entry, NULL,
-                                  SILC_MESSAGE_FLAG_NOTICE |
-                                  SILC_MESSAGE_FLAG_UTF8,
-                                  message ? message : argv[1],
-                                  message ? strlen(message) : argv_lens[1],
-                                  TRUE);
-
-  printformat_module("fe-common/silc", server, chanrec->entry->channel_name,
-                    MSGLEVEL_NOTICES, SILCTXT_CHANNEL_OWNNOTICE, 
-                     server->conn->local_entry->nickname, argv[1]);
-
-  for (i = 0; i < argc; i++)
-    silc_free(argv[i]);
-  silc_free(argv_lens);
-  silc_free(argv_types);
+  if (target != NULL) {
+    if (target_type == SEND_TARGET_CHANNEL) {
+      if (silc_send_channel(server, target, (message != NULL ? message : msg),
+                           SILC_MESSAGE_FLAG_NOTICE | SILC_MESSAGE_FLAG_UTF8 |
+                           (g_hash_table_lookup(optlist, "sign") != NULL ?
+                            SILC_MESSAGE_FLAG_SIGNED : 0))) {
+       if (g_hash_table_lookup(optlist, "sign"))
+          signal_emit("message silc signed_own_notice", 3, server, msg, target);
+       else
+          signal_emit("message silc own_notice", 3, server, msg, target);
+      }
+    } else {
+      if (silc_send_msg(server, target, (message != NULL ? message : msg),
+                       (message != NULL ? strlen(message) : strlen(msg)),
+                       SILC_MESSAGE_FLAG_NOTICE | SILC_MESSAGE_FLAG_UTF8 |
+                       (g_hash_table_lookup(optlist, "sign") != NULL ?
+                        SILC_MESSAGE_FLAG_SIGNED : 0))) {
+       if (g_hash_table_lookup(optlist, "sign"))
+         signal_emit("message silc signed_own_private_notice", 3,
+                         server, msg, target);
+       else
+         signal_emit("message silc own_private_notice", 3,
+                         server, msg, target);
+      }
+    }
+  }
+
+  cmd_params_free(free_arg);
   silc_free(message);
 }
 
@@ -379,23 +397,23 @@ static void command_notice(const char *data, SILC_SERVER_REC *server,
 bool silc_set_away(const char *reason, SILC_SERVER_REC *server)
 {
   bool set;
-  
+
   if (!IS_SILC_SERVER(server) || !server->connected)
     return FALSE;
-  
+
   if (*reason == '\0') {
     /* Remove any possible away message */
     silc_client_set_away_message(silc_client, server->conn, NULL);
     set = FALSE;
 
-    printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, 
+    printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_UNSET_AWAY);
   } else {
     /* Set the away message */
     silc_client_set_away_message(silc_client, server->conn, (char *)reason);
     set = TRUE;
 
-    printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, 
+    printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_SET_AWAY, reason);
   }
 
@@ -420,8 +438,8 @@ static void command_away(const char *data, SILC_SERVER_REC *server,
   g_free_and_null(server->away_reason);
   if ((data) && (*data != '\0'))
     server->away_reason = g_strdup(data);
-  
-  silc_command_exec(server, "UMODE", 
+
+  silc_command_exec(server, "UMODE",
                    (server->away_reason != NULL) ? "+g" : "-g");
 }
 
@@ -459,28 +477,28 @@ static void keyagr_completion(SilcClient client,
       silc_client_add_private_message_key_ske(client, conn, client_entry,
                                              NULL, NULL, key, i->responder);
       printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
-                        SILCTXT_KEY_AGREEMENT_PRIVMSG, 
+                        SILCTXT_KEY_AGREEMENT_PRIVMSG,
                         client_entry->nickname);
       silc_ske_free_key_material(key);
     }
-    
+
     break;
-    
+
   case SILC_KEY_AGREEMENT_ERROR:
     printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_ERROR, client_entry->nickname);
     break;
-    
+
   case SILC_KEY_AGREEMENT_FAILURE:
     printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_FAILURE, client_entry->nickname);
     break;
-    
+
   case SILC_KEY_AGREEMENT_TIMEOUT:
     printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_TIMEOUT, client_entry->nickname);
     break;
-    
+
   case SILC_KEY_AGREEMENT_ABORTED:
     printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_ABORTED, client_entry->nickname);
@@ -491,15 +509,15 @@ static void keyagr_completion(SilcClient client,
                       SILCTXT_KEY_AGREEMENT_ALREADY_STARTED,
                       client_entry->nickname);
     break;
-    
+
   case SILC_KEY_AGREEMENT_SELF_DENIED:
     printformat_module("fe-common/silc", i->server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_SELF_DENIED);
     break;
-    
+
   default:
     break;
-  } 
+  }
 
   if (i)
     silc_free(i);
@@ -532,7 +550,7 @@ static void silc_client_command_key_get_clients(SilcClient client,
   KeyGetClients internal = (KeyGetClients)context;
 
   if (!clients) {
-    printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s", 
+    printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
              internal->nick);
     silc_free(internal->data);
     silc_free(internal->nick);
@@ -564,7 +582,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   unsigned char **argv;
   SilcUInt32 *argv_lens, *argv_types;
   char *bindhost = NULL;
+
   CMD_SILC_SERVER(server);
 
   if (!server || !IS_SILC_SERVER(server) || !server->connected)
@@ -599,7 +617,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
                           MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
        return;
       }
-      
+
       /* Find client entry */
       entrys = silc_client_get_clients_local(silc_client, conn, nickname,
                                             argv[2], &entry_count);
@@ -650,7 +668,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       if (type == 1 && client_entry) {
        /* Set private message key */
        bool responder = FALSE;
-       
+
        silc_client_del_private_message_key(silc_client, conn, client_entry);
 
        if (argc >= 6) {
@@ -680,14 +698,14 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
           too. */
        /* XXX for now we don't do this.  This feature is pretty stupid
           and should perhaps be removed altogether from SILC.
-       silc_client_send_private_message_key(silc_client, conn, 
+       silc_client_send_private_message_key(silc_client, conn,
                                             client_entry, TRUE);
        */
       } else if (type == 2) {
        /* Set private channel key */
        if (!(channel_entry->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
          printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                            SILCTXT_CH_PRIVATE_KEY_NOMODE, 
+                            SILCTXT_CH_PRIVATE_KEY_NOMODE,
                             channel_entry->channel_name);
          goto out;
        }
@@ -697,26 +715,26 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
        if (argc >= 7)
          hmac = argv[6];
 
-       if (!silc_client_add_channel_private_key(silc_client, conn, 
+       if (!silc_client_add_channel_private_key(silc_client, conn,
                                                 channel_entry, NULL,
                                                 cipher, hmac,
                                                 argv[4],
-                                                argv_lens[4])) {
+                                                argv_lens[4], NULL)) {
          printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                            SILCTXT_CH_PRIVATE_KEY_ERROR, 
+                            SILCTXT_CH_PRIVATE_KEY_ERROR,
                             channel_entry->channel_name);
          goto out;
        }
 
        printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
-                          SILCTXT_CH_PRIVATE_KEY_ADD, 
+                          SILCTXT_CH_PRIVATE_KEY_ADD,
                           channel_entry->channel_name);
       }
     }
 
     goto out;
   }
-  
+
   /* Unset command */
   if (!strcasecmp(argv[3], "unset")) {
     command = 2;
@@ -731,12 +749,12 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       int number;
 
       if (argc == 4)
-       silc_client_del_channel_private_keys(silc_client, conn, 
+       silc_client_del_channel_private_keys(silc_client, conn,
                                             channel_entry);
 
       if (argc > 4) {
        number = atoi(argv[4]);
-       keys = silc_client_list_channel_private_keys(silc_client, conn, 
+       keys = silc_client_list_channel_private_keys(silc_client, conn,
                                                     channel_entry,
                                                     &keys_count);
        if (!keys)
@@ -766,7 +784,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       int k, i, len;
       char buf[1024];
 
-      keys = silc_client_list_private_message_keys(silc_client, conn, 
+      keys = silc_client_list_private_message_keys(silc_client, conn,
                                                   &keys_count);
       if (!keys)
        goto out;
@@ -784,7 +802,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
            for (i = 0; i < 30 - len; i++)
              strcat(buf, " ");
          strcat(buf, " ");
-         
+
          len = strlen(keys[k].cipher);
          strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
          if (len < 14)
@@ -815,7 +833,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
            for (i = 0; i < 30 - len; i++)
              strcat(buf, " ");
          strcat(buf, " ");
-         
+
          len = strlen(keys[k].cipher);
          strncat(buf, keys[k].cipher, len > 14 ? 14 : len);
          if (len < 14)
@@ -840,7 +858,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       int k, i, len;
       char buf[1024];
 
-      keys = silc_client_list_channel_private_keys(silc_client, conn, 
+      keys = silc_client_list_channel_private_keys(silc_client, conn,
                                                   channel_entry,
                                                   &keys_count);
 
@@ -850,7 +868,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
 
       if (!keys)
        goto out;
-      
+
       for (k = 0; k < keys_count; k++) {
        memset(buf, 0, sizeof(buf));
        strncat(buf, "  ", 2);
@@ -862,19 +880,19 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
          for (i = 0; i < 16 - len; i++)
            strcat(buf, " ");
        strcat(buf, " ");
-       
+
        len = strlen(silc_hmac_get_name(keys[k]->hmac));
        strncat(buf, silc_hmac_get_name(keys[k]->hmac), len > 16 ? 16 : len);
        if (len < 16)
          for (i = 0; i < 16 - len; i++)
            strcat(buf, " ");
        strcat(buf, " ");
-       
+
        strcat(buf, "<hidden>");
 
        silc_say(silc_client, conn, SILC_CLIENT_MESSAGE_INFO, "%s", buf);
       }
-      
+
       silc_client_free_channel_private_keys(keys, keys_count);
     }
 
@@ -893,19 +911,19 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
     internal = silc_calloc(1, sizeof(*internal));
     internal->type = type;
     internal->server = server;
-    
+
     if (!hostname) {
       if (settings_get_bool("use_auto_addr")) {
-       
+
         hostname = (char *)settings_get_str("auto_public_ip");
 
-       /* If the hostname isn't set, treat this case as if auto_public_ip 
+       /* If the hostname isn't set, treat this case as if auto_public_ip
           wasn't set. */
         if ((hostname) && (*hostname == '\0')) {
            hostname = NULL;
         } else {
           bindhost = (char *)settings_get_str("auto_bind_ip");
-            
+
          /* if the bind_ip isn't set, but the public_ip IS, then assume then
             public_ip is the same value as the bind_ip. */
           if ((bindhost) && (*bindhost == '\0'))
@@ -940,7 +958,7 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       SilcUInt32 keys_count;
       int number;
 
-      keys = silc_client_list_channel_private_keys(silc_client, conn, 
+      keys = silc_client_list_channel_private_keys(silc_client, conn,
                                                   channel_entry,
                                                   &keys_count);
       if (!keys)
@@ -961,8 +979,8 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
       }
 
       /* Set the current channel private key */
-      silc_client_current_channel_private_key(silc_client, conn, 
-                                             channel_entry, 
+      silc_client_current_channel_private_key(silc_client, conn,
+                                             channel_entry,
                                              keys[chanrec->cur_key]);
       printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                         SILCTXT_CH_PRIVATE_KEY_CHANGE, chanrec->cur_key + 1,
@@ -985,9 +1003,9 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
                       SILCTXT_KEY_AGREEMENT, argv[2]);
     internal->responder = TRUE;
     silc_client_send_key_agreement(
-                          silc_client, conn, client_entry, hostname, 
-                          bindhost, port, 
-                          settings_get_int("key_exchange_timeout_secs"), 
+                          silc_client, conn, client_entry, hostname,
+                          bindhost, port,
+                          settings_get_int("key_exchange_timeout_secs"),
                           keyagr_completion, internal);
     if (!hostname)
       silc_free(internal);
@@ -998,8 +1016,8 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
     printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
                       SILCTXT_KEY_AGREEMENT_NEGOTIATE, argv[2]);
     internal->responder = FALSE;
-    silc_client_perform_key_agreement(silc_client, conn, client_entry, 
-                                     hostname, port, keyagr_completion, 
+    silc_client_perform_key_agreement(silc_client, conn, client_entry,
+                                     hostname, port, keyagr_completion,
                                      internal);
     goto out;
   }
@@ -1008,12 +1026,192 @@ static void command_key(const char *data, SILC_SERVER_REC *server,
   silc_free(nickname);
 }
 
-/* Lists locally saved client and server public keys. */
+void silc_list_key(const char *pub_filename, int verbose)
+{
+  SilcPublicKey public_key;
+  SilcPublicKeyIdentifier ident;
+  char *fingerprint, *babbleprint;
+  unsigned char *pk;
+  SilcUInt32 pk_len;
+  SilcPKCS pkcs;
+  SilcUInt32 key_len = 0;
+  int is_server_key = (strstr(pub_filename, "serverkeys") != NULL);
+
+  if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
+                                SILC_PKCS_FILE_PEM) == FALSE)
+    if (silc_pkcs_load_public_key((char *)pub_filename, &public_key,
+                                  SILC_PKCS_FILE_BIN) == FALSE) {
+      printformat_module("fe-common/silc", NULL, NULL,
+                         MSGLEVEL_CRAP, SILCTXT_LISTKEY_LOADPUB,
+                         pub_filename);
+      return;
+    }
+
+  ident = silc_pkcs_decode_identifier(public_key->identifier);
+
+  pk = silc_pkcs_public_key_encode(public_key, &pk_len);
+  fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
+  babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
+
+  if (silc_pkcs_alloc(public_key->name, &pkcs)) {
+    key_len = silc_pkcs_public_key_set(pkcs, public_key);
+    silc_pkcs_free(pkcs);
+  }
 
+  printformat_module("fe-common/silc", NULL, NULL,
+                     MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_FILE,
+                     pub_filename);
+
+  if (verbose)
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_ALG,
+                       public_key->name);
+  if (key_len && verbose)
+    printformat_module("fe-common/silc", NULL, NULL,
+                        MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_BITS,
+                        (unsigned int)key_len);
+  if (ident->realname && (!is_server_key || verbose))
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_RN,
+                       ident->realname);
+  if (ident->username && verbose)
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_UN,
+                       ident->username);
+  if (ident->host && (is_server_key || verbose))
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_HN,
+                       ident->host);
+  if (ident->email && verbose)
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_EMAIL,
+                       ident->email);
+  if (ident->org && verbose)
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_ORG,
+                       ident->org);
+  if (ident->country && verbose)
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_C,
+                       ident->country);
+
+  if (verbose) {
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_FINGER,
+                       fingerprint);
+    printformat_module("fe-common/silc", NULL, NULL,
+                       MSGLEVEL_CRAP, SILCTXT_LISTKEY_PUB_BABL,
+                       babbleprint);
+  }
+
+  silc_free(fingerprint);
+  silc_free(babbleprint);
+  silc_free(pk);
+  silc_pkcs_public_key_free(public_key);
+  silc_pkcs_free_identifier(ident);
+
+}
+
+
+void silc_list_keys_in_dir(const char *dirname, const char *where)
+{
+  DIR *dir;
+  struct dirent *entry;
+
+  dir = opendir(dirname);
+
+  if (dir == NULL)
+         cmd_return_error(CMDERR_ERRNO);
+
+  printformat_module("fe-common/silc", NULL, NULL,
+                     MSGLEVEL_CRAP, SILCTXT_LISTKEY_LIST,
+                     where);
+
+  rewinddir(dir);
+
+  while ((entry = readdir(dir)) != NULL) {
+    /* try to open everything that isn't a directory */
+    struct stat buf;
+    char filename[256];
+
+    snprintf(filename, sizeof(filename) - 1, "%s/%s", dirname, entry->d_name);
+    if (!stat(filename, &buf) && S_ISREG(buf.st_mode))
+      silc_list_key(filename, FALSE);
+  }
+
+  closedir(dir);
+}
+
+void silc_list_file(const char *filename)
+{
+
+  char path[256];
+  struct stat buf;
+
+  snprintf(path, sizeof(path) - 1, "%s", filename);
+  if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+    goto list_key;
+
+  snprintf(path, sizeof(path) - 1, "%s/%s", get_irssi_dir(), filename);
+  if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+    goto list_key;
+
+  snprintf(path,sizeof(path) - 1, "%s/clientkeys/%s", get_irssi_dir(),
+          filename);
+  if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+    goto list_key;
+
+  snprintf(path,sizeof(path) - 1, "%s/serverkeys/%s", get_irssi_dir(),
+          filename);
+  if (!stat(path, &buf) && S_ISREG(buf.st_mode))
+    goto list_key;
+
+  return;
+
+list_key:
+
+  silc_list_key(path, TRUE);
+
+}
+
+/* Lists locally saved client and server public keys. */
 static void command_listkeys(const char *data, SILC_SERVER_REC *server,
                             WI_ITEM_REC *item)
 {
+  GHashTable *optlist;
+  char *filename;
+  void *free_arg;
+  char dirname[256];
+
+  if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS |
+                     PARAM_FLAG_GETREST, "listkeys", &optlist,
+                     &filename))
+    return;
+
+  if (*filename != '\0') {
+
+    silc_list_file(filename);
 
+  } else {
+    int clients, servers;
+
+    clients = (g_hash_table_lookup(optlist, "clients") != NULL);
+    servers = (g_hash_table_lookup(optlist, "servers") != NULL);
+
+    if (!(clients || servers))
+      clients = servers = 1;
+
+    if (servers) {
+      snprintf(dirname, sizeof(dirname) - 1, "%s/serverkeys", get_irssi_dir());
+      silc_list_keys_in_dir(dirname, "server");
+    }
+
+    if (clients) {
+      snprintf(dirname, sizeof(dirname) - 1, "%s/clientkeys", get_irssi_dir());
+      silc_list_keys_in_dir(dirname, "client");
+    }
+  }
+  cmd_params_free(free_arg);
 }
 
 void silc_channels_init(void)
@@ -1030,7 +1228,11 @@ void silc_channels_init(void)
   command_bind_silc("notice", MODULE_NAME, (SIGNAL_FUNC) command_notice);
   command_bind_silc("away", MODULE_NAME, (SIGNAL_FUNC) command_away);
   command_bind_silc("key", MODULE_NAME, (SIGNAL_FUNC) command_key);
-/*  command_bind_silc("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys); */
+  command_bind("listkeys", MODULE_NAME, (SIGNAL_FUNC) command_listkeys);
+
+  command_set_options("listkeys", "clients servers");
+  command_set_options("action", "sign channel");
+  command_set_options("notice", "sign channel");
 
   silc_nicklist_init();
 }
@@ -1049,7 +1251,7 @@ void silc_channels_deinit(void)
   command_unbind("notice", (SIGNAL_FUNC) command_notice);
   command_unbind("away", (SIGNAL_FUNC) command_away);
   command_unbind("key", (SIGNAL_FUNC) command_key);
-/*  command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys); */
+  command_unbind("listkeys", (SIGNAL_FUNC) command_listkeys);
 
   silc_nicklist_deinit();
 }
diff --git a/apps/irssi/src/silc/core/silc-chatnets.c b/apps/irssi/src/silc/core/silc-chatnets.c
new file mode 100644 (file)
index 0000000..8fbaf2d
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ silc-chatnets.c : irssi
+
+    Copyright (C) 1999-2000 Timo Sirainen
+    Copyright (C) 2003 Jochen Eisinger
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "module.h"
+#include "signals.h"
+#include "lib-config/iconfig.h"
+#include "settings.h"
+
+#include "silc-chatnets.h"
+
+void silcnet_create(SILC_CHATNET_REC *rec)
+{
+       g_return_if_fail(rec != NULL);
+
+       rec->chat_type = SILC_PROTOCOL;
+        chatnet_create((CHATNET_REC *) rec);
+}
+
+static void sig_chatnet_read(SILC_CHATNET_REC *rec, CONFIG_NODE *node)
+{
+       if (!IS_SILC_CHATNET(rec))
+               return;
+       
+       /* read settings */
+}
+
+static void sig_chatnet_saved(SILC_CHATNET_REC *rec, CONFIG_NODE *node)
+{
+       if (!IS_SILC_CHATNET(rec))
+               return;
+
+       /* save settings */
+}
+
+static void sig_chatnet_destroyed(SILC_CHATNET_REC *rec)
+{
+       if (!IS_SILC_CHATNET(rec))
+               return;
+
+       /* free eventually allocated memory */
+}
+
+
+void silc_chatnets_init(void)
+{
+       signal_add("chatnet read", (SIGNAL_FUNC) sig_chatnet_read);
+       signal_add("chatnet saved", (SIGNAL_FUNC) sig_chatnet_saved);
+       signal_add("chatnet destroyed", (SIGNAL_FUNC) sig_chatnet_destroyed);
+}
+
+void silc_chatnets_deinit(void)
+{
+       GSList *tmp, *next;
+
+       for (tmp = chatnets; tmp != NULL; tmp = next) {
+               CHATNET_REC *rec = tmp->data;
+
+               next = tmp->next;
+               if (IS_SILC_CHATNET(rec))
+                        chatnet_destroy(rec);
+       }
+
+       signal_remove("chatnet read", (SIGNAL_FUNC) sig_chatnet_read);
+       signal_remove("chatnet saved", (SIGNAL_FUNC) sig_chatnet_saved);
+       signal_remove("chatnet destroyed", (SIGNAL_FUNC) sig_chatnet_destroyed);
+}
diff --git a/apps/irssi/src/silc/core/silc-chatnets.h b/apps/irssi/src/silc/core/silc-chatnets.h
new file mode 100644 (file)
index 0000000..e9a1f67
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __SILC_CHATNETS_H
+#define __SILC_CHATNETS_H
+
+#include "chat-protocols.h"
+#include "chatnets.h"
+
+/* returns SILC_CHATNET_REC if it's SILC network, NULL if it isn't */
+#define SILC_CHATNET(chatnet) \
+       PROTO_CHECK_CAST(CHATNET(chatnet), SILC_CHATNET_REC, chat_type, "SILC")
+
+#define IS_SILC_CHATNET(chatnet) \
+       (SILC_CHATNET(chatnet) ? TRUE : FALSE)
+
+#define IS_SILCNET(silcnet) IS_SILC_CHATNET(silcnet)
+#define SILCNET(silcnet) SILC_CHATNET(silcnet)
+
+struct _SILC_CHATNET_REC {
+#include "chatnet-rec.h"
+};
+
+typedef struct _SILC_CHATNET_REC SILC_CHATNET_REC;
+
+void silcnet_create(SILC_CHATNET_REC *rec);
+
+#define silc_chatnet_find(name) \
+       SILC_CHATNET(chatnet_find(name))
+#define silcnet_find(name) silc_chatnet_find(name)
+
+void silc_chatnets_init(void);
+void silc_chatnets_deinit(void);
+
+#endif
diff --git a/apps/irssi/src/silc/core/silc-cmdqueue.c b/apps/irssi/src/silc/core/silc-cmdqueue.c
new file mode 100644 (file)
index 0000000..2e9092d
--- /dev/null
@@ -0,0 +1,148 @@
+#include "module.h"
+#include "silc-cmdqueue.h"
+
+#include <stdarg.h>
+
+GHashTable *cmd_queues;
+
+void silc_queue_init(void)
+{
+  cmd_queues = g_hash_table_new(NULL, NULL);
+}
+
+static void cmd_list_remove_cb(char *cmd)
+{
+  g_free(cmd);
+}
+
+static int cmd_queue_remove_cb(void *key, GSList *list)
+{
+  if ((list != NULL) && (list->next != NULL)) {
+    g_slist_foreach(list, (GFunc) cmd_list_remove_cb, NULL);
+    g_slist_free(list);
+  }
+
+  return TRUE;
+}
+
+void silc_queue_deinit(void)
+{
+  g_hash_table_foreach_remove(cmd_queues, (GHRFunc) cmd_queue_remove_cb, NULL);
+  g_hash_table_destroy(cmd_queues);
+}
+
+void silc_queue_flush(SilcClientConnection conn)
+{
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+
+  if (list != NULL) {
+    GSList *tmp;
+
+    for (tmp = g_slist_next(list); tmp != NULL; tmp = g_slist_next(tmp))
+      silc_client_command_call(silc_client, conn, tmp->data);
+
+    g_slist_foreach(list, (GFunc) cmd_list_remove_cb, NULL);
+    /* free all but the first element ... */
+    g_slist_free(g_slist_remove_link(list, list));
+  }
+}
+
+void silc_queue_enable(SilcClientConnection conn)
+{
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+
+  if (list == NULL)
+    g_hash_table_insert(cmd_queues, conn, g_slist_alloc());
+}
+
+void silc_queue_disable(SilcClientConnection conn)
+{
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+
+   if (list != NULL) {
+     silc_queue_flush(conn);
+     g_slist_free(list);
+     g_hash_table_remove(cmd_queues, conn);
+   }
+}
+
+bool silc_queue_command_call(SilcClient client,
+                       SilcClientConnection conn,
+                       const char *command_line, ...)
+{
+  va_list ap;
+  char *cmd = (char *) command_line;
+  GSList *list = g_hash_table_lookup(cmd_queues, conn);
+  bool need_free = FALSE;
+
+  va_start(ap, command_line);
+
+  if (command_line == NULL) {
+    char *tmp = va_arg(ap, char *);
+
+    need_free = TRUE;
+
+    if (tmp == NULL) {
+      va_end(ap);
+      return FALSE;
+    }
+
+    cmd = g_strdup(tmp);
+
+    for (tmp = va_arg(ap, char *); tmp != NULL; tmp = va_arg(ap, char *)) {
+      char *old = cmd;
+
+      cmd = g_strconcat(cmd, " ", tmp, NULL);
+      g_free(old);
+    }
+
+  }
+
+  va_end(ap);
+
+  if (!silc_term_utf8()) {
+    int len = silc_utf8_encoded_len(cmd, strlen(cmd), SILC_STRING_LOCALE);
+    char *message = silc_calloc(len + 1, sizeof(*cmd));
+    if (message == NULL) {
+
+      if (need_free)
+        g_free(cmd);
+
+      g_error("file %s: line %d: assertion `message != NULL' failed.",
+                __FILE__, __LINE__);
+
+      return FALSE;
+    }
+    silc_utf8_encode(cmd, strlen(cmd), SILC_STRING_LOCALE, message, len);
+
+    if (need_free)
+      g_free(cmd);
+
+    need_free = TRUE;
+    cmd = g_strdup(message);
+
+    silc_free(message);
+  }
+
+  /* queueing disabled -> immediate execution */
+  if (list == NULL) {
+    bool result = silc_client_command_call(client, conn, cmd);
+
+    if (need_free)
+      g_free(cmd);
+
+    return result;
+  }
+
+  g_hash_table_remove(cmd_queues, conn);
+  g_hash_table_insert(cmd_queues, conn, g_slist_append(list, g_strdup(cmd)));
+
+  if (need_free)
+    g_free(cmd);
+
+  return TRUE;
+}
+
+bool silc_queue_get_state(SilcClientConnection conn) {
+  return g_hash_table_lookup(cmd_queues, conn) != NULL;
+}
diff --git a/apps/irssi/src/silc/core/silc-cmdqueue.h b/apps/irssi/src/silc/core/silc-cmdqueue.h
new file mode 100644 (file)
index 0000000..ee18373
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __SILC_CMDQUEUE_H
+#define __SILC_CMDQUEUE_H
+
+/* wrappers for queuing commands:
+
+   basically the same as the correspondening silc_client_* functions 
+   with one additional parameter:
+   
+   bool sync           - command must be executed in sync (i.e. no
+                         other command may be send before completion)
+   */
+
+bool silc_queue_command_call(SilcClient client, 
+                               SilcClientConnection conn,
+                               const char *command_line, ...);
+
+#define silc_queue_command_pending silc_client_command_pending
+
+/*
+   enable and/or disable command queueing. If command queueing is
+   disabled, all silc_queue_* calls will immedially call silc_client_*
+   functions. If queueing is enabled, all silc_queue_* calls don't have
+   any effect until queueing is disabled again.
+
+   queueing is enabled and disabled for each SilcClientConnection
+   seperatly.
+
+   If queueing is enabled, silc_queue_flush will send all currently
+   queued commands but won't disable queueing.
+ */
+void silc_queue_enable(SilcClientConnection conn);
+void silc_queue_disable(SilcClientConnection conn);
+void silc_queue_flush(SilcClientConnection conn);
+
+/* returns true if queueing is enabled */
+bool silc_queue_get_state(SilcClientConnection conn);
+
+void silc_queue_init(void);
+void silc_queue_deinit(void);
+
+#endif
index 421fe6fc5874bd4ef432666f32c78bf229c94d53..e61e1c1d023ae4ce8826bb35c19565a511685d52 100644 (file)
@@ -29,6 +29,8 @@
 #include "silc-channels.h"
 #include "silc-queries.h"
 #include "silc-nicklist.h"
+#include "silc-chatnets.h"
+#include "silc-cmdqueue.h"
 
 #include "signals.h"
 #include "levels.h"
@@ -42,7 +44,7 @@
 static char *opt_pkcs = NULL;
 static int opt_bits = 0;
 
-static int idletag;
+static int idletag = -1;
 
 SilcClient silc_client = NULL;
 extern SilcClientOperations ops;
@@ -260,6 +262,16 @@ void silc_opt_callback(poptContext con,
                       const struct poptOption *opt,
                       const char *arg, void *data)
 {
+  if (strcmp(opt->longName, "nick") == 0) {
+    g_free(silc_client->nickname);  
+    silc_client->nickname = g_strdup(arg);
+  }
+
+  if (strcmp(opt->longName, "hostname") == 0) {
+    silc_free(silc_client->hostname);  
+    silc_client->hostname = g_strdup(arg);
+  }
+
   if (strcmp(opt->longName, "list-ciphers") == 0) {
     silc_cipher_register_default();
     silc_client_list_ciphers();
@@ -331,22 +343,19 @@ void silc_opt_callback(poptContext con,
 static void sig_init_finished(void)
 {
   /* Check ~/.silc directory and public and private keys */
-  if (!silc_client_check_silc_dir()) {
-    idletag = -1;
+  if (!silc_client_check_silc_dir())
     exit(1);
-  }
 
   /* Load public and private key */
-  if (!silc_client_load_keys(silc_client)) {
-    idletag = -1;
+  if (!silc_client_load_keys(silc_client))
     exit(1);
-  }
 
   /* Initialize the SILC client */
-  if (!silc_client_init(silc_client)) {
-    idletag = -1;
+  if (!silc_client_init(silc_client))
     exit(1);
-  }
+
+  /* register SILC scheduler */
+  idletag = g_timeout_add(5, (GSourceFunc) my_silc_scheduler, NULL);
 }
 
 /* Init SILC. Called from src/fe-text/silc.c */
@@ -401,6 +410,7 @@ void silc_core_init(void)
   settings_add_int("server", "connauth_request_secs", 2);
   settings_add_int("server", "heartbeat", 300);
   settings_add_bool("server", "ignore_message_signatures", FALSE);
+  settings_add_str("server", "session_filename", "session.$chatnet");
 
   /* Requested Attributes settings */
   settings_add_bool("silc", "attr_allow", TRUE);
@@ -477,13 +487,13 @@ void silc_core_init(void)
   chat_protocol_register(rec);
   g_free(rec);
 
+  silc_queue_init();
   silc_server_init();
   silc_channels_init();
   silc_queries_init();
   silc_expandos_init();
   silc_lag_init();
-
-  idletag = g_timeout_add(5, (GSourceFunc) my_silc_scheduler, NULL);
+  silc_chatnets_init();
 
   module_register("silc", "core");
 }
@@ -492,22 +502,23 @@ void silc_core_init(void)
 
 void silc_core_deinit(void)
 {
-  if (idletag != -1) {
-    signal_emit("chat protocol deinit", 1,
-               chat_protocol_find("SILC"));
-    signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
-    signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished);
-
-    silc_server_deinit();
-    silc_channels_deinit();
-    silc_queries_deinit();
-    silc_expandos_deinit();
-    silc_lag_deinit();
-    
-    chat_protocol_unregister("SILC");
-    
+  if (idletag != -1)
     g_source_remove(idletag);
-  }
+  
+  signal_emit("chat protocol deinit", 1,
+       chat_protocol_find("SILC"));
+  signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
+  signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished);
+
+  silc_queue_deinit();
+  silc_server_deinit();
+  silc_channels_deinit();
+  silc_queries_deinit();
+  silc_expandos_deinit();
+  silc_lag_deinit();
+  silc_chatnets_deinit();
+  
+  chat_protocol_unregister("SILC");
   
   g_free(silc_client->username);
   g_free(silc_client->realname);
index 1c5ad516dacd679d13b9839f4cfc266309139a05..ba2d9b30ebbed5b1690a607f51bb9101cb45dd06 100644 (file)
@@ -82,7 +82,7 @@ static int sig_check_lag(void)
                                server_disconnect((SERVER_REC *) rec);
                        }
                } else if (rec->lag_last_check+lag_check_time < now &&
-                        rec->cmdcount == 0 && rec->connected) {
+                        rec->connected) {
                        /* no commands in buffer - get the lag */
                        lag_get(rec);
                }
index 9daff3b01c4bbd21e41dc62acd101e1ba6ebac91..3da82845914b2b6947a61b4fd68561f34058483d 100644 (file)
@@ -1,6 +1,6 @@
 /*
 
-  silc-queries.c 
+  silc-queries.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
@@ -433,6 +433,8 @@ void silc_query_attributes_default(SilcClient client,
        mask |= SILC_ATTRIBUTE_CONTACT_MMS;
       if (!strcasecmp(*entry, "CHAT"))
        mask |= SILC_ATTRIBUTE_CONTACT_CHAT;
+      if (!strcasecmp(*entry, "VIDEO"))
+       mask |= SILC_ATTRIBUTE_CONTACT_VIDEO;
     }
     silc_client_attribute_add(silc_client, conn,
                              SILC_ATTRIBUTE_PREFERRED_CONTACT, (void *)mask,
@@ -702,6 +704,8 @@ void silc_query_attributes_print(SILC_SERVER_REC *server,
          silc_strncat(tmp, sizeof(tmp), "SMS ", strlen(" SMS"));
        if (mask & SILC_ATTRIBUTE_CONTACT_MMS)
          silc_strncat(tmp, sizeof(tmp), "MMS ", strlen(" MMS"));
+       if (mask & SILC_ATTRIBUTE_CONTACT_VIDEO)
+         silc_strncat(tmp, sizeof(tmp), "VIDEO ", strlen(" VIDEO"));
        printformat_module("fe-common/silc", server, NULL,
                           MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_CONTACT, tmp);
       }
@@ -876,7 +880,7 @@ void silc_query_attributes_print(SILC_SERVER_REC *server,
 
   if (verify->userpk.data) {
     silc_verify_public_key(client, conn, SILC_SOCKET_TYPE_CLIENT,
-                          verify->userpk.data, verify->userpk.data_len, 
+                          verify->userpk.data, verify->userpk.data_len,
                           SILC_SKE_PK_TYPE_SILC,
                           silc_query_attributes_print_final, verify);
   } else {
@@ -917,10 +921,10 @@ static void silc_query_attributes_print_final(bool success, void *context)
   for (i = 0; i < strlen(fingerprint); i++)
     if (fingerprint[i] == ' ')
       fingerprint[i] = '_';
-  
+
   /* Filename for dir */
   tmp = fingerprint + strlen(fingerprint) - 9;
-  snprintf(filename, sizeof(filename) - 1, "%s/friends/%s", 
+  snprintf(filename, sizeof(filename) - 1, "%s/friends/%s",
           get_irssi_dir(), tmp);
   silc_free(fingerprint);
 
@@ -968,7 +972,7 @@ static void silc_query_attributes_accept(const char *line, void *context)
 
     /* Filename for dir */
     tmp = fingerprint + strlen(fingerprint) - 9;
-    snprintf(filename, sizeof(filename) - 1, "%s/friends/%s", 
+    snprintf(filename, sizeof(filename) - 1, "%s/friends/%s",
             get_irssi_dir(), tmp);
 
     /* Create dir if it doesn't exist */
@@ -1020,7 +1024,7 @@ static void silc_query_attributes_accept(const char *line, void *context)
     }
 
     /* Save MIME message data */
-    if (verify->extension.mime) {
+    if (verify->message.mime) {
       memset(filename2, 0, sizeof(filename2));
       snprintf(filename2, sizeof(filename2) - 1, "%s/status_message.mime",
               filename);
index 0287eb772649ac12d94a9766660881d03276f01b..476205d450e0cfcf3c00b81e9f4da307873bf1b2 100644 (file)
@@ -1,7 +1,7 @@
 /*
   silc-server.c : irssi
 
-  Copyright (C) 2000 - 2003 Timo Sirainen
+  Copyright (C) 2000 - 2005 Timo Sirainen
                             Pekka Riikonen <priikone@silcnet.org>
 
   This program is free software; you can redistribute it and/or modify
 
 #include "servers-setup.h"
 
+#include "client_ops.h"
 #include "silc-servers.h"
 #include "silc-channels.h"
 #include "silc-queries.h"
 #include "silc-nicklist.h"
+#include "silc-cmdqueue.h"
 #include "window-item-def.h"
 
 #include "fe-common/core/printtext.h"
@@ -50,9 +52,9 @@
 void silc_servers_reconnect_init(void);
 void silc_servers_reconnect_deinit(void);
 
-static int silc_send_channel(SILC_SERVER_REC *server,
-                             char *channel, char *msg,
-                             SilcMessageFlags flags)
+int silc_send_channel(SILC_SERVER_REC *server,
+                     char *channel, char *msg,
+                     SilcMessageFlags flags)
 {
   SILC_CHANNEL_REC *rec;
 
@@ -115,7 +117,7 @@ static void silc_send_msg_clients(SilcClient client,
        real (formatted) nickname and the nick (maybe formatted) that
        use gave. This is to assure that `nick' does not match
        `nick@host'. */
-    if (strcasecmp(rec->nick, clients[0]->nickname)) {
+    if (!silc_utf8_strcasecmp(rec->nick, clients[0]->nickname)) {
       printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
                "%s: There is no such client", rec->nick);
       goto out;
@@ -134,8 +136,8 @@ static void silc_send_msg_clients(SilcClient client,
   g_free(rec);
 }
 
-static int silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
-                         int msg_len, SilcMessageFlags flags)
+int silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
+                 int msg_len, SilcMessageFlags flags)
 {
   PRIVMSG_REC *rec;
   SilcClientEntry *clients;
@@ -163,7 +165,7 @@ static int silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
     silc_client_get_clients(silc_client, server->conn,
                            nickname, NULL, silc_send_msg_clients, rec);
     silc_free(nickname);
-    return FALSE;
+    return TRUE;
   }
 
   /* Send the private message directly */
@@ -174,51 +176,46 @@ static int silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
   return TRUE;
 }
 
-void silc_send_mime(SILC_SERVER_REC *server, WI_ITEM_REC *to,
-                   const char *data,
-                   const char *enc, const char *type)
+void silc_send_mime(SILC_SERVER_REC *server, int channel, const char *to,
+                   const char *data, int sign)
 {
-  SILC_CHANNEL_REC *channel;
-  QUERY_REC *query;
   char *unescaped_data;
   SilcUInt32 unescaped_data_len;
-  char *mime_data;
-  int mime_data_len;
+  int target_type;
 
-  if (!(IS_SILC_SERVER(server)) || (data == NULL) || (to == NULL) ||
-      (enc == NULL) || (type == NULL))
+  if (!(IS_SILC_SERVER(server)) || (data == NULL) || (to == NULL))
     return;
 
-  unescaped_data = silc_unescape_data(data, &unescaped_data_len);
-
-#define SILC_MIME_HEADER "MIME-Version: 1.0\r\nContent-Type: %s\r\nContent-Transfer-Encoding: %s\r\n\r\n"
+  if (channel) {
+    target_type = SEND_TARGET_CHANNEL;
+  } else {
+    target_type = server_ischannel(SERVER(server), to) ?
+      SEND_TARGET_CHANNEL : SEND_TARGET_NICK;
+  }
 
-  mime_data_len = unescaped_data_len + strlen(SILC_MIME_HEADER) - 4
-    + strlen(enc) + strlen(type);
-  if (mime_data_len >= SILC_PACKET_MAX_LEN)
-    return;
+  unescaped_data = silc_unescape_data(data, &unescaped_data_len);
 
-  /* we risk to large packets here... */
-  mime_data = silc_calloc(mime_data_len, sizeof(*mime_data));
-  snprintf(mime_data, mime_data_len, SILC_MIME_HEADER, type, enc);
-  memmove(mime_data + strlen(SILC_MIME_HEADER) - 4 + strlen(enc) + strlen(type),
-         unescaped_data, unescaped_data_len);
+  if (target_type == SEND_TARGET_CHANNEL) {
+    SILC_CHANNEL_REC *rec;
 
-#undef SILC_MIME_HEADER
+    rec = silc_channel_find(server, to);
+    if (rec == NULL || rec->entry == NULL) {
+      cmd_return_error(CMDERR_NOT_JOINED);
+    }
 
-  if (IS_SILC_CHANNEL(to)) {
-    channel = SILC_CHANNEL(to);
-    silc_client_send_channel_message(silc_client, server->conn, channel->entry,
-                                    NULL, SILC_MESSAGE_FLAG_DATA,
-                                    mime_data, mime_data_len, TRUE);
-  } else if (IS_SILC_QUERY(to)) {
-    query = SILC_QUERY(to);
-    silc_send_msg(server, query->name, mime_data, mime_data_len,
-                 SILC_MESSAGE_FLAG_DATA);
+    silc_client_send_channel_message(silc_client, server->conn, rec->entry,
+                                    NULL, SILC_MESSAGE_FLAG_DATA |
+                                    (sign ? SILC_MESSAGE_FLAG_SIGNED : 0),
+                                    unescaped_data, unescaped_data_len, TRUE);
+  } else {
+    silc_send_msg(server, (char *)to, unescaped_data, unescaped_data_len,
+                 SILC_MESSAGE_FLAG_DATA |
+                 (sign ? SILC_MESSAGE_FLAG_SIGNED : 0));
 
   }
 
-  silc_free(mime_data);
+  signal_stop();
+
   silc_free(unescaped_data);
 }
 
@@ -240,7 +237,7 @@ const char *get_nick_flags(void)
 static void send_message(SILC_SERVER_REC *server, char *target,
                         char *msg, int target_type)
 {
-  char *message = NULL;
+  char *message = NULL, *t = NULL;
   int len;
 
   g_return_if_fail(server != NULL);
@@ -248,21 +245,30 @@ static void send_message(SILC_SERVER_REC *server, char *target,
   g_return_if_fail(msg != NULL);
 
   if (!silc_term_utf8()) {
-    len = silc_utf8_encoded_len(msg, strlen(msg), SILC_STRING_LANGUAGE);
+    len = silc_utf8_encoded_len(msg, strlen(msg), SILC_STRING_LOCALE);
     message = silc_calloc(len + 1, sizeof(*message));
     g_return_if_fail(message != NULL);
-    silc_utf8_encode(msg, strlen(msg), SILC_STRING_LANGUAGE, message, len);
+    silc_utf8_encode(msg, strlen(msg), SILC_STRING_LOCALE, message, len);
   }
 
   if (target_type == SEND_TARGET_CHANNEL)
     silc_send_channel(server, target, message ? message : msg,
                      SILC_MESSAGE_FLAG_UTF8);
-  else
-    silc_send_msg(server, target, message ? message : msg,
+  else {
+    if (!silc_term_utf8()) {
+      len = silc_utf8_encoded_len(target, strlen(target), SILC_STRING_LOCALE);
+      t = silc_calloc(len + 1, sizeof(*t));
+      g_return_if_fail(t != NULL);
+      silc_utf8_encode(target, strlen(target), SILC_STRING_LOCALE, t, len);
+    }
+
+    silc_send_msg(server, t ? t : target, message ? message : msg,
                  message ? strlen(message) : strlen(msg),
                  SILC_MESSAGE_FLAG_UTF8);
+  }
 
   silc_free(message);
+  silc_free(t);
 }
 
 void silc_send_heartbeat(SilcSocketConnection sock,
@@ -281,7 +287,7 @@ static void sig_connected(SILC_SERVER_REC *server)
 {
   SilcClientConnection conn;
   SilcClientConnectionParams params;
-  char file[256];
+  char *file;
   int fd;
 
   if (!IS_SILC_SERVER(server))
@@ -289,8 +295,7 @@ static void sig_connected(SILC_SERVER_REC *server)
 
   /* Try to read detached session data and use it if found. */
   memset(&params, 0, sizeof(params));
-  memset(file, 0, sizeof(file));
-  snprintf(file, sizeof(file) - 1, "%s/session", get_irssi_dir());
+  file = silc_get_session_filename(server);
   params.detach_data = silc_file_readfile(file, &params.detach_data_len);
   if (params.detach_data)
     params.detach_data[params.detach_data_len] = 0;
@@ -303,12 +308,10 @@ static void sig_connected(SILC_SERVER_REC *server)
   server->conn = conn;
 
   if (params.detach_data)
-    keyboard_entry_redirect(NULL,
-                           "-- Resuming old session, may take a while ...",
-                           ENTRY_REDIRECT_FLAG_HIDDEN, server);
+    printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP,
+                       SILCTXT_REATTACH, server->tag);
 
   silc_free(params.detach_data);
-  unlink(file);
 
   fd = g_io_channel_unix_get_fd(net_sendbuffer_handle(server->handle));
 
@@ -426,18 +429,18 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
 /* SYNTAX: SILCOPER <username> [-pubkey] */
 /* SYNTAX: TOPIC <channel> [<topic>] */
 /* SYNTAX: UMODE +|-<modes> */
-/* SYNTAX: WHOIS <nickname>[@<hostname>] [-details] [<count>] */
+/* SYNTAX: WHOIS [<nickname>[@<hostname>]] [-details] [-pubkey <pubkeyfile>] [<count>] */
 /* SYNTAX: WHOWAS <nickname>[@<hostname>] [<count>] */
 /* SYNTAX: CLOSE <server> [<port>] */
 /* SYNTAX: SHUTDOWN */
 /* SYNTAX: MOTD [<server>] */
 /* SYNTAX: LIST [<channel>] */
 /* SYNTAX: ME <message> */
-/* SYNTAX: ACTION <channel> <message> */
+/* SYNTAX: ACTION [-sign] [-channel] <target> <message> */
 /* SYNTAX: AWAY [<message>] */
 /* SYNTAX: INFO [<server>] */
 /* SYNTAX: NICK <nickname> */
-/* SYNTAX: NOTICE <message> */
+/* SYNTAX: NOTICE [-sign] [-channel] <target> <message> */
 /* SYNTAX: PART [<channel>] */
 /* SYNTAX: PING */
 /* SYNTAX: SCONNECT <server> [<port>] */
@@ -448,10 +451,11 @@ char *silc_server_get_channels(SILC_SERVER_REC *server)
 /* SYNTAX: FILE */
 /* SYNTAX: JOIN <channel> [<passphrase>] [-cipher <cipher>] [-hmac <hmac>] [-founder] [-auth [<pubkeyfile> <privkeyfile> [<privkey passphrase>]]]*/
 /* SYNTAX: DETACH */
-/* SYNTAX: WATCH [<-add | -del> <nickname>] */
+/* SYNTAX: WATCH [<-add | -del> <nickname>] [-pubkey +|-<pubkeyfile>] */
 /* SYNTAX: STATS */
 /* SYNTAX: ATTR [<-del> <option> [{ <value>}]] */
 /* SYNTAX: SMSG [<-channel>] <target> <message> */
+/* SYNTAX: LISTKEYS [-servers] [-clients] [<public key file>] */
 
 void silc_command_exec(SILC_SERVER_REC *server,
                       const char *command, const char *args)
@@ -461,7 +465,7 @@ void silc_command_exec(SILC_SERVER_REC *server,
 
   /* Call the command */
   data = g_strconcat(command, " ", args, NULL);
-  silc_client_command_call(silc_client, server->conn, data);
+  silc_queue_command_call(silc_client, server->conn, data);
   g_free(data);
 }
 
@@ -542,26 +546,35 @@ static void command_smsg(const char *data, SILC_SERVER_REC *server,
   }
 
   if (target != NULL) {
-    char *message = NULL;
+    char *message = NULL, *t = NULL;
     int len, result;
 
     if (!silc_term_utf8()) {
-      len = silc_utf8_encoded_len(msg, strlen(msg), SILC_STRING_LANGUAGE);
+      len = silc_utf8_encoded_len(msg, strlen(msg), SILC_STRING_LOCALE);
       message = silc_calloc(len + 1, sizeof(*message));
       g_return_if_fail(message != NULL);
-      silc_utf8_encode(msg, strlen(msg), SILC_STRING_LANGUAGE, message, len);
+      silc_utf8_encode(msg, strlen(msg), SILC_STRING_LOCALE, message, len);
     }
 
     if (target_type == SEND_TARGET_CHANNEL)
       result = silc_send_channel(server, target, message ? message : msg,
                                 SILC_MESSAGE_FLAG_UTF8 |
                                 SILC_MESSAGE_FLAG_SIGNED);
-    else
-      result = silc_send_msg(server, target, message ? message : msg,
+    else {
+      if (!silc_term_utf8()) {
+       len = silc_utf8_encoded_len(target, strlen(target),
+                                   SILC_STRING_LOCALE);
+       t = silc_calloc(len + 1, sizeof(*t));
+       g_return_if_fail(t != NULL);
+       silc_utf8_encode(target, strlen(target), SILC_STRING_LOCALE, t, len);
+      }
+      result = silc_send_msg(server, t ? t : target, message ? message : msg,
                             message ? strlen(message) : strlen(msg),
                             SILC_MESSAGE_FLAG_UTF8 |
                             SILC_MESSAGE_FLAG_SIGNED);
+    }
     silc_free(message);
+    silc_free(t);
     if (!result)
       goto out;
   }
@@ -602,6 +615,9 @@ static void silc_client_file_monitor(SilcClient client,
   FtpSession ftp;
   char fsize[32];
 
+  if (status == SILC_CLIENT_FILE_MONITOR_CLOSED)
+    return;
+
   snprintf(fsize, sizeof(fsize) - 1, "%llu", ((filesize + 1023) / 1024));
 
   silc_dlist_start(server->ftp_sessions);
@@ -632,9 +648,12 @@ static void silc_client_file_monitor(SilcClient client,
     silc_schedule_task_add(silc_client->schedule, 0,
                           silc_client_file_close_later, ftp,
                           1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-    if (ftp == server->current_session)
-      server->current_session = NULL;
     silc_dlist_del(server->ftp_sessions, ftp);
+    if (ftp == server->current_session) {
+      server->current_session = NULL;
+      silc_dlist_start(server->ftp_sessions);
+      server->current_session = silc_dlist_get(server->ftp_sessions);
+    }
   }
 
   if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT) {
@@ -669,9 +688,13 @@ static void silc_client_file_monitor(SilcClient client,
       silc_schedule_task_add(silc_client->schedule, 0,
                             silc_client_file_close_later, ftp,
                             1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-      if (ftp == server->current_session)
-       server->current_session = NULL;
       silc_dlist_del(server->ftp_sessions, ftp);
+      if (ftp == server->current_session) {
+       server->current_session = NULL;
+       silc_dlist_start(server->ftp_sessions);
+       server->current_session = silc_dlist_get(server->ftp_sessions);
+      }
+
     }
   }
 
@@ -690,9 +713,13 @@ static void silc_client_file_monitor(SilcClient client,
       silc_schedule_task_add(silc_client->schedule, 0,
                             silc_client_file_close_later, ftp,
                             1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-      if (ftp == server->current_session)
-       server->current_session = NULL;
       silc_dlist_del(server->ftp_sessions, ftp);
+      if (ftp == server->current_session) {
+       server->current_session = NULL;
+       silc_dlist_start(server->ftp_sessions);
+       server->current_session = silc_dlist_get(server->ftp_sessions);
+      }
+
     }
   }
 }
@@ -882,16 +909,28 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
 
       ret = silc_client_file_receive(silc_client, conn,
                                     silc_client_file_monitor, server, NULL,
-                                    server->current_session->session_id);
+                                    server->current_session->session_id,
+                                    NULL, NULL);
       if (ret != SILC_CLIENT_FILE_OK) {
        if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
          printformat_module("fe-common/silc", server, NULL,
                             MSGLEVEL_CRAP, SILCTXT_FILE_ALREADY_STARTED,
                             server->current_session->client_entry->nickname);
-       else
+       else {
          printformat_module("fe-common/silc", server, NULL,
                             MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
                             server->current_session->client_entry->nickname);
+
+         silc_client_file_close(silc_client, conn,
+                                server->current_session->session_id);
+         silc_dlist_del(server->ftp_sessions, server->current_session);
+         silc_free(server->current_session->filepath);
+         silc_free(server->current_session);
+         server->current_session = NULL;
+
+         silc_dlist_start(server->ftp_sessions);
+         server->current_session = silc_dlist_get(server->ftp_sessions);
+       }
       }
 
       goto out;
@@ -902,16 +941,26 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
       if (ftp->client_entry == client_entry && !ftp->filepath) {
        ret = silc_client_file_receive(silc_client, conn,
                                       silc_client_file_monitor, server,
-                                      NULL, ftp->session_id);
+                                      NULL, ftp->session_id, NULL, NULL);
        if (ret != SILC_CLIENT_FILE_OK) {
          if (ret == SILC_CLIENT_FILE_ALREADY_STARTED)
            printformat_module("fe-common/silc", server, NULL,
                               MSGLEVEL_CRAP, SILCTXT_FILE_ALREADY_STARTED,
                               client_entry->nickname);
-         else
+         else {
            printformat_module("fe-common/silc", server, NULL,
                               MSGLEVEL_CRAP, SILCTXT_FILE_CLIENT_NA,
                               client_entry->nickname);
+           silc_client_file_close(silc_client, conn, ftp->session_id);
+           silc_dlist_del(server->ftp_sessions, ftp);
+           if (ftp == server->current_session) {
+             server->current_session = NULL;
+             silc_dlist_start(server->ftp_sessions);
+             server->current_session = silc_dlist_get(server->ftp_sessions);
+           }
+           silc_free(ftp->filepath);
+           silc_free(ftp);
+         }
        }
        break;
       }
@@ -967,6 +1016,9 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
       silc_free(server->current_session->filepath);
       silc_free(server->current_session);
       server->current_session = NULL;
+
+      silc_dlist_start(server->ftp_sessions);
+      server->current_session = silc_dlist_get(server->ftp_sessions);
       goto out;
     }
 
@@ -978,9 +1030,12 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
                           MSGLEVEL_CRAP, SILCTXT_FILE_CLOSED,
                           client_entry->nickname,
                           ftp->filepath ? ftp->filepath : "[N/A]");
-       if (ftp == server->current_session)
-         server->current_session = NULL;
        silc_dlist_del(server->ftp_sessions, ftp);
+       if (ftp == server->current_session) {
+         server->current_session = NULL;
+         silc_dlist_start(server->ftp_sessions);
+         server->current_session = silc_dlist_get(server->ftp_sessions);
+       }
        silc_free(ftp->filepath);
        silc_free(ftp);
        break;
@@ -1011,6 +1066,7 @@ static void command_file(const char *data, SILC_SERVER_REC *server,
       printformat_module("fe-common/silc", server, NULL,
                         MSGLEVEL_CRAP, SILCTXT_FILE_SHOW_LINE,
                         ftp->client_entry->nickname,
+                        ftp->session_id,
                         ftp->send ? "send" : "receive",
                         (SilcUInt32)(ftp->offset + 1023) / 1024,
                         (SilcUInt32)(ftp->filesize + 1023) / 1024,
index bf3f3b7066722009fe2b0b6ff863c249083ed325..cc6b94439f1f5ca551c4f7931014df02320b0a67 100644 (file)
@@ -38,18 +38,6 @@ typedef struct {
 #define STRUCT_SERVER_CONNECT_REC SILC_SERVER_CONNECT_REC
 typedef struct {
 #include "server-rec.h"
-  /* Command sending queue */
-  int cmdcount;                /* number of commands in `cmdqueue'. Can be more than
-                          there actually is, to make flood control remember
-                          how many messages can be sent before starting the
-                          flood control */
-  int cmd_last_split;  /* Last command wasn't sent entirely to server.
-                          First item in `cmdqueue' should be re-sent. */
-  GSList *cmdqueue;
-  GTimeVal last_cmd;   /* last time command was sent to server */
-  
-  GSList *idles;       /* Idle queue - send these commands to server
-                          if there's nothing else to do */
 
   SilcDList ftp_sessions;
   FtpSession current_session;
@@ -73,4 +61,9 @@ void silc_server_free_ftp(SILC_SERVER_REC *server,
                          SilcClientEntry client_entry);
 bool silc_term_utf8(void);
 
+int silc_send_msg(SILC_SERVER_REC *server, char *nick, char *msg,
+                 int msg_len, SilcMessageFlags flags);
+int silc_send_channel(SILC_SERVER_REC *server,
+                     char *channel, char *msg,
+                     SilcMessageFlags flags);
 #endif
index 604fee76a8bc00bc049da734c7e02d1968c688bd..d166e1fb1fd97906c0a210a2e53eb874036c00f0 100644 (file)
@@ -1,14 +1,13 @@
 #
 #  Makefile.am
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
index 0d594b9d9891049af8823d33408054cd9316dc73..5d94f74b9a02c69d38ed45df0c1b16dc8daabf0c 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -206,7 +206,12 @@ void silc_server_command_process(SilcServer server,
   ctx->payload = silc_command_payload_parse(packet->buffer->data,
                                            packet->buffer->len);
   if (!ctx->payload) {
-    SILC_LOG_ERROR(("Bad command payload, packet dropped"));
+    SILC_LOG_ERROR(("Bad command payload, dropped (%s:%d [%s])",
+                  sock->hostname, sock->port,
+                  (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
+                   sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
+                   sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
+                   "Router")));
     silc_packet_context_free(packet);
     silc_socket_free(ctx->sock);
     silc_free(ctx);
@@ -621,48 +626,54 @@ SILC_SERVER_CMD_FUNC(nick)
   SilcBuffer packet, nidp, oidp = NULL;
   SilcClientID *new_id;
   SilcUInt32 nick_len;
-  char *nick;
+  unsigned char *nick, *nickc = NULL;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
-  int nickfail = 0;
 
   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
     goto out;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
 
-  /* Check nickname */
+  /* Get nickname */
   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
   if (!nick) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
                                          SILC_STATUS_ERR_BAD_NICKNAME, 0);
     goto out;
   }
-  if (nick_len > 128)
+
+  /* Truncate over long nicks */
+  if (nick_len > 128) {
     nick[128] = '\0';
-  if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
+    nick_len = 128;
+  }
+
+  /* Check for valid nickname string.  This is cached, original is saved
+     in the client context. */
+  nickc = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128, NULL);
+  if (!nickc) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
                                          SILC_STATUS_ERR_BAD_NICKNAME, 0);
     goto out;
   }
 
   /* Check for same nickname */
-  if (!strcmp(client->nickname, nick)) {
+  if (strlen(client->nickname) == nick_len &&
+      !memcmp(client->nickname, nick, nick_len)) {
     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+    silc_free(nickc);
     goto send_reply;
   }
 
   /* Create new Client ID */
-  while (!silc_id_create_client_id(cmd->server, cmd->server->id,
-                                  cmd->server->rng,
-                                  cmd->server->md5hash, nick,
-                                  &new_id)) {
-    nickfail++;
-    if (nickfail > 9) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
-                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
-      goto out;
-    }
-    snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
+  if (!silc_id_create_client_id(cmd->server, cmd->server->id,
+                               cmd->server->rng,
+                               cmd->server->md5hash,
+                               nickc, strlen(nickc), &new_id)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
+                                         SILC_STATUS_ERR_BAD_NICKNAME, 0);
+    silc_free(nickc);
+    goto out;
   }
 
   /* Send notify about nickname change to our router. We send the new
@@ -689,7 +700,7 @@ SILC_SERVER_CMD_FUNC(nick)
   client->nickname = strdup(nick);
 
   /* Update client cache */
-  silc_idcache_add(server->local_list->clients, client->nickname,
+  silc_idcache_add(server->local_list->clients, nickc,
                   client->id, (void *)client, 0, NULL);
 
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
@@ -712,7 +723,7 @@ SILC_SERVER_CMD_FUNC(nick)
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
                                                SILC_STATUS_OK, 0, ident, 2,
                                                2, nidp->data, nidp->len,
-                                               3, nick, strlen(nick));
+                                               3, nick, nick_len);
   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
                          0, packet->data, packet->len, FALSE);
 
@@ -757,6 +768,12 @@ silc_server_command_list_send_reply(SilcServerCommandContext cmd,
       valid_rcount++;
   }
 
+  if (!lch_count && !gch_count) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
+                                         SILC_STATUS_OK, 0);
+    return;
+  }
+
   status = SILC_STATUS_OK;
   if ((lch_count + gch_count) > 1)
     status = SILC_STATUS_LIST_START;
@@ -978,6 +995,13 @@ SILC_SERVER_CMD_FUNC(topic)
       goto out;
     }
 
+    if (!silc_utf8_valid(tmp, strlen(tmp))) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
+                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                           0);
+      goto out;
+    }
+
     /* See whether the client is on channel and has rights to change topic */
     if (!silc_server_client_on_channel(client, channel, &chl)) {
       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
@@ -1174,7 +1198,7 @@ SILC_SERVER_CMD_FUNC(invite)
 
     /* Check if the ID is in the list already */
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
       if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
        tmp = NULL;
        break;
@@ -1241,8 +1265,14 @@ SILC_SERVER_CMD_FUNC(invite)
       }
 
       /* Now add or delete the information. */
-      silc_server_inviteban_process(server, channel->invite_list,
-                                   (SilcUInt8)atype[0], args);
+      if (!silc_server_inviteban_process(server, channel->invite_list,
+                                        (SilcUInt8)atype[0], args)) {
+       silc_server_command_send_status_reply(
+                                   cmd, SILC_COMMAND_INVITE,
+                                   SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                   0);
+       goto out;
+      }
     }
     silc_argument_payload_free(args);
   }
@@ -1256,7 +1286,7 @@ SILC_SERVER_CMD_FUNC(invite)
                                          channel->invite_list)),
                       SILC_STR_END);
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
                                              type);
     silc_hash_table_list_reset(&htl);
@@ -1332,14 +1362,17 @@ SILC_TASK_CALLBACK(silc_server_command_quit_cb)
   SilcServer server = app_context;
   QuitInternal q = (QuitInternal)context;
 
-  /* Free all client specific data, such as client entry and entires
-     on channels this client may be on. */
-  silc_server_free_client_data(server, q->sock, q->sock->user_data,
-                              TRUE, q->signoff);
-  q->sock->user_data = NULL;
+  if (q->sock->user_data) {
+    /* Free all client specific data, such as client entry and entires
+       on channels this client may be on. */
+    silc_server_free_client_data(server, q->sock, q->sock->user_data,
+                                TRUE, q->signoff);
+    q->sock->user_data = NULL;
+  }
 
-  /* Close the connection on our side */
-  silc_server_close_connection(server, q->sock);
+  if (!SILC_IS_DISCONNECTED(q->sock))
+    /* Close the connection on our side */
+    silc_server_close_connection(server, q->sock);
 
   silc_socket_free(q->sock);
   silc_free(q->signoff);
@@ -1526,7 +1559,7 @@ SILC_SERVER_CMD_FUNC(info)
   SilcBuffer packet, idp;
   unsigned char *tmp;
   SilcUInt32 tmp_len;
-  char *dest_server, *server_info = NULL, *server_name;
+  char *dest_server = NULL, *server_info = NULL, *server_name;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   SilcServerEntry entry = NULL;
   SilcServerID *server_id = NULL;
@@ -1535,6 +1568,16 @@ SILC_SERVER_CMD_FUNC(info)
 
   /* Get server name */
   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
+  if (dest_server) {
+    /* Check server name. */
+    dest_server = silc_identifier_check(dest_server, strlen(dest_server),
+                                       SILC_STRING_UTF8, 256, &tmp_len);
+    if (!dest_server) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+                                           SILC_STATUS_ERR_BAD_SERVER, 0);
+      goto out;
+    }
+  }
 
   /* Get Server ID */
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
@@ -1570,7 +1613,7 @@ SILC_SERVER_CMD_FUNC(info)
   if ((!dest_server && !server_id && !entry) || (entry &&
                                                 entry == server->id_entry) ||
       (dest_server && !cmd->pending &&
-       !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
+       !memcmp(dest_server, server->server_name, strlen(dest_server)))) {
     /* Send our reply */
     char info_string[256];
 
@@ -1648,11 +1691,15 @@ SILC_SERVER_CMD_FUNC(info)
   silc_free(server_id);
 
   if (!entry) {
-    if (dest_server)
+    if (dest_server) {
+      silc_free(dest_server);
+      dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_INFO,
                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
                                           2, dest_server,
                                           strlen(dest_server));
+      dest_server = NULL;
+    }
     goto out;
   }
 
@@ -1677,6 +1724,7 @@ SILC_SERVER_CMD_FUNC(info)
   silc_buffer_free(idp);
 
  out:
+  silc_free(dest_server);
   silc_server_command_free(cmd);
 }
 
@@ -1836,7 +1884,7 @@ static void silc_server_command_join_channel(SilcServer server,
   SilcSocketConnection sock = cmd->sock;
   unsigned char *tmp;
   SilcUInt32 tmp_len, user_count;
-  unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
+  unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4], ulimit[4];
   SilcClientEntry client;
   SilcChannelClientEntry chl;
   SilcBuffer reply, chidp, clidp, keyp = NULL;
@@ -1863,9 +1911,11 @@ static void silc_server_command_join_channel(SilcServer server,
                                      &resolve);
     if (!client) {
       if (!resolve || cmd->pending) {
-       silc_server_command_send_status_reply(
+       tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+       silc_server_command_send_status_data(
                                         cmd, SILC_COMMAND_JOIN,
-                                        SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
+                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
+                                        2, tmp, tmp_len);
        goto out;
       }
 
@@ -1962,7 +2012,10 @@ static void silc_server_command_join_channel(SilcServer server,
     if (!strchr(client->nickname, '@')) {
       silc_strncat(check2, sizeof(check2), "@", 1);
       silc_strncat(check2, sizeof(check2),
-                  server->server_name, strlen(server->server_name));
+                  SILC_IS_LOCAL(client) ? server->server_name :
+                  client->router->server_name,
+                  SILC_IS_LOCAL(client) ? strlen(server->server_name) :
+                  strlen(client->router->server_name));
     }
     silc_strncat(check2, sizeof(check2), "!", 1);
     silc_strncat(check2, sizeof(check2),
@@ -2042,6 +2095,7 @@ static void silc_server_command_join_channel(SilcServer server,
       passphrase = silc_memdup(tmp, tmp_len);
 
     if (!passphrase || !channel->passphrase ||
+       strlen(channel->passphrase) != strlen(passphrase) ||
         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
       chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
@@ -2116,6 +2170,8 @@ static void silc_server_command_join_channel(SilcServer server,
   SILC_PUT32_MSB(channel->mode, mode);
   SILC_PUT32_MSB(created, tmp2);
   SILC_PUT32_MSB(user_count, tmp3);
+  if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
+    SILC_PUT32_MSB(channel->user_limit, ulimit);
 
   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
@@ -2143,7 +2199,7 @@ static void silc_server_command_join_channel(SilcServer server,
                       SILC_STR_END);
 
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
+    while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
       invite_list = silc_argument_payload_encode_one(invite_list,
                                                     reply->data,
                                                     reply->len, tmp_len);
@@ -2162,7 +2218,7 @@ static void silc_server_command_join_channel(SilcServer server,
                       SILC_STR_END);
 
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
+    while (silc_hash_table_get(&htl, (void *)&tmp_len, (void *)&reply))
       ban_list = silc_argument_payload_encode_one(ban_list,
                                                  reply->data,
                                                  reply->len, tmp_len);
@@ -2174,7 +2230,7 @@ static void silc_server_command_join_channel(SilcServer server,
 
   reply =
     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
-                                        SILC_STATUS_OK, 0, ident, 15,
+                                        SILC_STATUS_OK, 0, ident, 16,
                                         2, channel->channel_name,
                                         strlen(channel->channel_name),
                                         3, chidp->data, chidp->len,
@@ -2201,7 +2257,13 @@ static void silc_server_command_join_channel(SilcServer server,
                                         15, fkey ? fkey->data : NULL,
                                         fkey ? fkey->len : 0,
                                         16, chpklist ? chpklist->data : NULL,
-                                        chpklist ? chpklist->len : 0);
+                                        chpklist ? chpklist->len : 0,
+                                        17, (channel->mode &
+                                             SILC_CHANNEL_MODE_ULIMIT ?
+                                             ulimit : NULL),
+                                        (channel->mode &
+                                         SILC_CHANNEL_MODE_ULIMIT ?
+                                         sizeof(ulimit) : 0));
 
   /* Send command reply */
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
@@ -2283,7 +2345,7 @@ SILC_SERVER_CMD_FUNC(join)
   SilcServer server = cmd->server;
   unsigned char *auth, *cauth;
   SilcUInt32 tmp_len, auth_len, cauth_len;
-  char *tmp, *channel_name = NULL, *cipher, *hmac;
+  char *tmp, *channel_name, *channel_namec = NULL, *cipher, *hmac;
   SilcChannelEntry channel;
   SilcUInt32 umode = 0;
   bool created = FALSE, create_key = TRUE;
@@ -2299,12 +2361,19 @@ SILC_SERVER_CMD_FUNC(join)
                                          0);
     goto out;
   }
-  channel_name = tmp;
 
-  if (tmp_len > 256)
-    channel_name[255] = '\0';
+  /* Truncate over long channel names */
+  if (tmp_len > 256) {
+    tmp[256] = '\0';
+    tmp_len = 256;
+  }
+  channel_name = tmp;
 
-  if (silc_server_name_bad_chchars(channel_name, tmp_len) == TRUE) {
+  /* Check for valid channel name.  This is cached, the original is saved
+     in the channel context. */
+  channel_namec = silc_channel_name_check(tmp, tmp_len, SILC_STRING_UTF8, 256,
+                                         NULL);
+  if (!channel_namec) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                          SILC_STATUS_ERR_BAD_CHANNEL, 0);
     goto out;
@@ -2314,15 +2383,15 @@ SILC_SERVER_CMD_FUNC(join)
   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
   if (!tmp) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
-                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                         SILC_STATUS_ERR_NO_CLIENT_ID,
                                          0);
     goto out;
   }
   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
   if (!client_id) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
-                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
-                                         0);
+    silc_server_command_send_status_data(cmd, SILC_COMMAND_JOIN,
+                                        SILC_STATUS_ERR_BAD_CLIENT_ID, 0,
+                                        2, tmp, tmp_len);
     goto out;
   }
 
@@ -2334,7 +2403,7 @@ SILC_SERVER_CMD_FUNC(join)
 
   /* See if the channel exists */
   channel = silc_idlist_find_channel_by_name(server->local_list,
-                                            channel_name, NULL);
+                                            channel_namec, NULL);
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
@@ -2414,7 +2483,7 @@ SILC_SERVER_CMD_FUNC(join)
        /* We are router and the channel does not seem exist so we will check
           our global list as well for the channel. */
        channel = silc_idlist_find_channel_by_name(server->global_list,
-                                                  channel_name, NULL);
+                                                  channel_namec, NULL);
        if (!channel) {
          /* Channel really does not exist, create it */
          channel = silc_server_create_new_channel(server, server->id, cipher,
@@ -2450,7 +2519,7 @@ SILC_SERVER_CMD_FUNC(join)
       /* We are router and the channel does not seem exist so we will check
         our global list as well for the channel. */
       channel = silc_idlist_find_channel_by_name(server->global_list,
-                                                channel_name, NULL);
+                                                channel_namec, NULL);
       if (!channel) {
        /* Channel really does not exist, create it */
        channel = silc_server_create_new_channel(server, server->id, cipher,
@@ -2513,6 +2582,7 @@ SILC_SERVER_CMD_FUNC(join)
   silc_free(client_id);
 
  out:
+  silc_free(channel_namec);
   silc_server_command_free(cmd);
 }
 
@@ -2524,7 +2594,7 @@ SILC_SERVER_CMD_FUNC(motd)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   SilcBuffer packet, idp;
-  char *motd, *dest_server;
+  char *motd, *dest_server = NULL;
   SilcUInt32 motd_len;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
 
@@ -2539,7 +2609,17 @@ SILC_SERVER_CMD_FUNC(motd)
     goto out;
   }
 
-  if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
+  /* Check server name */
+  dest_server = silc_identifier_check(dest_server, strlen(dest_server),
+                                     SILC_STRING_UTF8, 256, NULL);
+  if (!dest_server) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
+                                         SILC_STATUS_ERR_BAD_SERVER,
+                                         0);
+    goto out;
+  }
+
+  if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
     /* Send our MOTD */
 
     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
@@ -2556,14 +2636,14 @@ SILC_SERVER_CMD_FUNC(motd)
       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
                                                    SILC_STATUS_OK, 0,
                                                    ident, 2,
-                                                   2, idp, idp->len,
+                                                   2, idp->data, idp->len,
                                                    3, motd, motd_len);
     } else {
       /* No motd */
       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
                                                    SILC_STATUS_OK, 0,
                                                    ident, 1,
-                                                   2, idp, idp->len);
+                                                   2, idp->data, idp->len);
     }
 
     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
@@ -2606,7 +2686,10 @@ SILC_SERVER_CMD_FUNC(motd)
       goto out;
     }
 
-    if (!entry && !cmd->pending && !server->standalone) {
+    /* Send to primary router only if we don't know the server
+     * the client requested or if the server is not locally connected */
+    if ((!entry || !(entry->data.status & SILC_IDLIST_STATUS_LOCAL))
+       && !cmd->pending && !server->standalone) {
       /* Send to the primary router */
       SilcBuffer tmpbuf;
       SilcUInt16 old_ident;
@@ -2631,17 +2714,20 @@ SILC_SERVER_CMD_FUNC(motd)
     }
 
     if (!entry) {
+      silc_free(dest_server);
+      dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0,
                                           2, dest_server,
                                           strlen(dest_server));
+      dest_server = NULL;
       goto out;
     }
 
-    idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
+    idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
                                                  SILC_STATUS_OK, 0, ident, 2,
-                                                 2, idp, idp->len,
+                                                 2, idp->data, idp->len,
                                                  3, entry->motd,
                                                  entry->motd ?
                                                  strlen(entry->motd) : 0);
@@ -2652,6 +2738,7 @@ SILC_SERVER_CMD_FUNC(motd)
   }
 
  out:
+  silc_free(dest_server);
   silc_server_command_free(cmd);
 }
 
@@ -2691,18 +2778,11 @@ SILC_SERVER_CMD_FUNC(umode)
     }
 
     /* Anonymous mode cannot be set by client */
-    if (mask & SILC_UMODE_ANONYMOUS) {
-      if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
-       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
-                                             SILC_STATUS_ERR_PERM_DENIED, 0);
-       goto out;
-      }
-    } else {
-      if (client->mode & SILC_UMODE_ANONYMOUS) {
-       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
-                                             SILC_STATUS_ERR_PERM_DENIED, 0);
-       goto out;
-      }
+    if (mask & SILC_UMODE_ANONYMOUS &&
+       !(client->mode & SILC_UMODE_ANONYMOUS)) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
+                                           SILC_STATUS_ERR_PERM_DENIED, 0);
+      goto out;
     }
 
     /* Update statistics */
@@ -2714,6 +2794,10 @@ SILC_SERVER_CMD_FUNC(umode)
        server->stat.my_aways--;
     }
 
+    /* If the client has anonymous mode set, preserve it. */
+    if (client->mode & SILC_UMODE_ANONYMOUS)
+      mask |= SILC_UMODE_ANONYMOUS;
+
     /* Change the mode */
     client->mode = mask;
 
@@ -2754,7 +2838,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   SilcChannelClientEntry chl;
   SilcBuffer packet, cidp;
   unsigned char *tmp, *tmp_id, *tmp_mask, *chpkdata = NULL;
-  char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
+  char *cipher = NULL, *hmac = NULL, *passphrase = NULL, ulimit[4];
   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2, chpklen;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
   bool set_mask = FALSE, set_chpk = FALSE;
@@ -3134,7 +3218,6 @@ SILC_SERVER_CMD_FUNC(cmode)
        channel->founder_key = NULL;
        goto out;
       }
-    has_founder:
     }
   } else {
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
@@ -3145,6 +3228,7 @@ SILC_SERVER_CMD_FUNC(cmode)
       }
     }
   }
+ has_founder:
 
   if (mode_mask & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
@@ -3164,7 +3248,6 @@ SILC_SERVER_CMD_FUNC(cmode)
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE, st, 0);
        goto out;
       }
-    has_pk_list:
     }
   } else {
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
@@ -3176,14 +3259,17 @@ SILC_SERVER_CMD_FUNC(cmode)
       }
     }
   }
+ has_pk_list:
 
   /* Finally, set the mode */
   old_mask = channel->mode = mode_mask;
 
   /* Send CMODE_CHANGE notify. */
   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+  if (mode_mask & SILC_CHANNEL_MODE_ULIMIT)
+    SILC_PUT32_MSB(channel->user_limit, ulimit);
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
-                                    SILC_NOTIFY_TYPE_CMODE_CHANGE, 7,
+                                    SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
                                     cidp->data, cidp->len,
                                     tmp_mask, 4,
                                     cipher, cipher ? strlen(cipher) : 0,
@@ -3193,7 +3279,11 @@ SILC_SERVER_CMD_FUNC(cmode)
                                     fkey ? fkey->data : NULL,
                                     fkey ? fkey->len : 0,
                                     chpkdata ? chpkdata : NULL,
-                                    chpkdata ? chpklen : 0);
+                                    chpkdata ? chpklen : 0,
+                                    mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
+                                    ulimit : NULL,
+                                    mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
+                                    sizeof(ulimit) : 0);
 
   /* Set CMODE notify type to network */
   if (chpkdata && chpklen)
@@ -3209,14 +3299,21 @@ SILC_SERVER_CMD_FUNC(cmode)
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
-                                               SILC_STATUS_OK, 0, ident, 4,
+                                               SILC_STATUS_OK, 0, ident, 5,
                                                2, tmp_id, tmp_len2,
                                                3, tmp_mask, 4,
                                                4, fkey ? fkey->data : NULL,
                                                fkey ? fkey->len : 0,
                                                5, chpklist ? chpklist->data :
                                                NULL, chpklist ? chpklist->len
-                                               : 0);
+                                               : 0,
+                                               6, (mode_mask &
+                                                   SILC_CHANNEL_MODE_ULIMIT ?
+                                                   ulimit : NULL),
+                                               (mode_mask &
+                                                SILC_CHANNEL_MODE_ULIMIT ?
+                                                sizeof(ulimit) : 0));
+
   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
                          packet->data, packet->len, FALSE);
 
@@ -3320,16 +3417,15 @@ SILC_SERVER_CMD_FUNC(cumode)
   /* Get target client's entry */
   target_client = silc_idlist_find_client_by_id(server->local_list,
                                                client_id, TRUE, NULL);
-  if (!target_client) {
+  if (!target_client)
     target_client = silc_idlist_find_client_by_id(server->global_list,
                                                  client_id, TRUE, NULL);
-  }
 
   if (target_client != client &&
       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
     silc_server_command_send_status_data(cmd, SILC_COMMAND_CUMODE,
-                                        SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0,
+                                        SILC_STATUS_ERR_NOT_YOU, 0,
                                         2, tmp_ch_id, tmp_ch_len);
     goto out;
   }
@@ -3362,7 +3458,8 @@ SILC_SERVER_CMD_FUNC(cumode)
   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
     if (target_client != client) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
-                                           SILC_STATUS_ERR_NOT_YOU, 0);
+                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
+                                           0);
       goto out;
     }
 
@@ -3406,16 +3503,23 @@ SILC_SERVER_CMD_FUNC(cumode)
       }
 
       /* There cannot be anyone else as founder on the channel now.  This
-        client is definitely the founder due to this authentication */
-      silc_hash_table_list(channel->user_list, &htl);
-      while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
-       if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
-         chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-         silc_server_force_cumode_change(server, NULL, channel, chl2,
-                                         chl2->mode);
-         break;
-       }
-      silc_hash_table_list_reset(&htl);
+        client is definitely the founder due to this authentication.  This
+        is done only on router, not on server, since server cannot know
+        whether router will accept this mode change or not.  XXX This
+        probably shouldn't be done anymore at all, may cause problems in
+        router-router connections too (maybe just AUTH_FAILED error should
+        be returned). -Pekka */
+      if (server->server_type == SILC_ROUTER) {
+       silc_hash_table_list(channel->user_list, &htl);
+       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
+         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
+           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, NULL, channel, chl2,
+                                           chl2->mode);
+           break;
+         }
+       silc_hash_table_list_reset(&htl);
+      }
 
       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
     }
@@ -3721,10 +3825,6 @@ SILC_SERVER_CMD_FUNC(kick)
                          packet->data, packet->len, FALSE);
   silc_buffer_free(packet);
 
-  /* Send command reply to sender */
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
-                                       SILC_STATUS_OK, 0);
-
   /* Send KICKED notify to local clients on the channel */
   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
@@ -3745,6 +3845,7 @@ SILC_SERVER_CMD_FUNC(kick)
       silc_argument_payload_encode_one(NULL, target_idp, target_idp_len, 3);
     SilcArgumentPayload args =
       silc_argument_payload_parse(ab->data, ab->len, 1);
+
     silc_server_inviteban_process(server, channel->invite_list, 1, args);
     silc_buffer_free(ab);
     silc_argument_payload_free(args);
@@ -3781,7 +3882,7 @@ SILC_SERVER_CMD_FUNC(oper)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-  unsigned char *username, *auth;
+  unsigned char *username = NULL, *auth;
   SilcUInt32 tmp_len;
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
@@ -3802,6 +3903,16 @@ SILC_SERVER_CMD_FUNC(oper)
     goto out;
   }
 
+  /* Check username */
+  username = silc_identifier_check(username, strlen(username),
+                                  SILC_STRING_UTF8, 128, &tmp_len);
+  if (!username) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
+                                         SILC_STATUS_ERR_BAD_USERNAME,
+                                         0);
+    goto out;
+  }
+
   /* Get the admin configuration */
   admin = silc_server_config_find_admin(server, cmd->sock->ip,
                                        username, client->nickname);
@@ -3874,6 +3985,7 @@ SILC_SERVER_CMD_FUNC(oper)
                                        SILC_STATUS_OK, 0);
 
  out:
+  silc_free(username);
   silc_server_command_free(cmd);
 }
 
@@ -3996,11 +4108,11 @@ SILC_SERVER_CMD_FUNC(watch)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   char *add_nick, *del_nick;
-  SilcUInt32 add_nick_len, del_nick_len, tmp_len;
-  char nick[128 + 1];
-  unsigned char hash[16], *tmp;
+  SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
+  unsigned char hash[16], *tmp,  *pk, *nick;
   SilcClientEntry client;
   SilcClientID *client_id = NULL;
+  SilcUInt16 old_ident;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
 
@@ -4008,7 +4120,11 @@ SILC_SERVER_CMD_FUNC(watch)
     if (!cmd->pending) {
       /* Send the command to router */
       SilcBuffer tmpbuf;
-      SilcUInt16 old_ident;
+
+      /* If backup receives this from primary, handle it locally */
+      if (server->server_type == SILC_BACKUP_ROUTER &&
+         cmd->sock == SILC_PRIMARY_ROUTE(server))
+       goto process_watch;
 
       SILC_LOG_DEBUG(("Forwarding WATCH to router"));
 
@@ -4028,21 +4144,30 @@ SILC_SERVER_CMD_FUNC(watch)
       cmd->pending = TRUE;
       silc_command_set_ident(cmd->payload, old_ident);
       silc_buffer_free(tmpbuf);
-    } else if (context2) {
-      /* Received reply from router, just send same data to the client. */
+      goto out;
+    } else {
       SilcServerCommandReplyContext reply = context2;
       SilcStatus status;
 
-      SILC_LOG_DEBUG(("Received reply to WATCH from router"));
+      if (!reply)
+        goto out;
+
       silc_command_get_status(reply->payload, &status, NULL);
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
-                                           0);
-    }
 
-    goto out;
+      /* Backup router handles the WATCH command also. */
+      if (server->server_type != SILC_BACKUP_ROUTER ||
+         SILC_STATUS_IS_ERROR(status)) {
+       /* Received reply from router, just send same data to the client. */
+       SILC_LOG_DEBUG(("Received reply to WATCH from router"));
+       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
+                                             0);
+       goto out;
+      }
+    }
   }
 
   /* We are router and keep the watch list for local cell */
+ process_watch:
 
   /* Get the client ID */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
@@ -4064,32 +4189,45 @@ SILC_SERVER_CMD_FUNC(watch)
   client = silc_idlist_find_client_by_id(server->local_list,
                                         client_id, TRUE, NULL);
   if (!client) {
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
-                                        SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0,
-                                        2, tmp, tmp_len);
-    goto out;
+    /* Backup checks global list also */
+    if (server->server_type == SILC_BACKUP_ROUTER)
+      client = silc_idlist_find_client_by_id(server->global_list,
+                                            client_id, TRUE, NULL);
+    if (!client) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
+                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                          0, 2, tmp, tmp_len);
+      goto out;
+    }
   }
 
+  /* Take public key for watching by public key */
+  pk = silc_argument_get_arg_type(cmd->args, 4, &pk_len);
+
   /* Take nickname */
   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
-  if (!add_nick && !del_nick) {
+  if (!add_nick && !del_nick && !pk) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
                                          0);
     goto out;
   }
 
-  if (add_nick && add_nick_len > 128)
+  if (add_nick && add_nick_len > 128) {
     add_nick[128] = '\0';
-  if (del_nick && del_nick_len > 128)
+    add_nick_len = 128;
+  }
+  if (del_nick && del_nick_len > 128) {
     del_nick[128] = '\0';
-
-  memset(nick, 0, sizeof(nick));
+    del_nick_len = 128;
+  }
 
   /* Add new nickname to be watched in our cell */
   if (add_nick) {
-    if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
+    nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
+                                &add_nick_len);
+    if (!nick) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
                                            SILC_STATUS_ERR_BAD_NICKNAME, 0);
       goto out;
@@ -4097,8 +4235,7 @@ SILC_SERVER_CMD_FUNC(watch)
 
     /* Hash the nick, we have the hash saved, not nicks because we can
        do one to one mapping to the nick from Client ID hash this way. */
-    silc_to_lower(add_nick, nick, sizeof(nick) - 1);
-    silc_hash_make(server->md5hash, nick, strlen(nick), hash);
+    silc_hash_make(server->md5hash, nick, add_nick_len, hash);
 
     /* Check whether this client is already watching this nickname */
     if (silc_hash_table_find_by_context(server->watcher_list, hash,
@@ -4107,21 +4244,25 @@ SILC_SERVER_CMD_FUNC(watch)
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
                                            SILC_STATUS_ERR_NICKNAME_IN_USE,
                                            0);
+      silc_free(nick);
       goto out;
     }
 
     /* Get the nickname from the watcher list and use the same key in
        new entries as well.  If key doesn't exist then create it. */
-    if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
+    if (!silc_hash_table_find(server->watcher_list, hash, (void *)&tmp, NULL))
       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
 
     /* Add the client to the watcher list with the specified nickname hash. */
     silc_hash_table_add(server->watcher_list, tmp, client);
+    silc_free(nick);
   }
 
   /* Delete nickname from watch list */
   if (del_nick) {
-    if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
+    nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
+                                &del_nick_len);
+    if (!nick) {
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
                                            SILC_STATUS_ERR_BAD_NICKNAME, 0);
       goto out;
@@ -4129,16 +4270,16 @@ SILC_SERVER_CMD_FUNC(watch)
 
     /* Hash the nick, we have the hash saved, not nicks because we can
        do one to one mapping to the nick from Client ID hash this way. */
-    silc_to_lower(del_nick, nick, sizeof(nick) - 1);
-    silc_hash_make(server->md5hash, nick, strlen(nick), hash);
+    silc_hash_make(server->md5hash, nick, del_nick_len, hash);
 
     /* Check that this client is watching for this nickname */
     if (!silc_hash_table_find_by_context(server->watcher_list, hash,
-                                        client, (void **)&tmp)) {
+                                        client, (void *)&tmp)) {
       /* Nickname is alredy being watched for this client */
       silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
                                           SILC_STATUS_ERR_NO_SUCH_NICK, 0,
-                                          2, nick, strlen(nick));
+                                          2, nick, del_nick_len);
+      silc_free(nick);
       goto out;
     }
 
@@ -4149,22 +4290,112 @@ SILC_SERVER_CMD_FUNC(watch)
        then free the key to not leak memory. */
     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
       silc_free(tmp);
+    silc_free(nick);
   }
 
+  /* Add/del public key */
+  if (pk) {
+    SilcUInt16 pkargc;
+    SilcArgumentPayload pkargs;
+    SilcUInt32 type;
+    SilcPublicKey public_key, pkkey;
+
+    if (pk_len < 2) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
+                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                           0);
+      goto out;
+    }
+
+    /* Get the argument from the Argument List Payload */
+    SILC_GET16_MSB(pkargc, pk);
+    pkargs = silc_argument_payload_parse(pk + 2, pk_len - 2, pkargc);
+    if (!pkargs) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
+                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                           0);
+      goto out;
+    }
+
+    pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
+    while (pk) {
+      if (!silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key))
+       continue;
+      if (type == 0x03)
+        type = 0x00;
+
+      if (type == 0x00) {
+       /* Add public key to watch list */
+
+       /* Check whether this client is already watching this public key */
+       if (silc_hash_table_find_by_context(server->watcher_list_pk,
+                                           public_key, client, NULL)) {
+         silc_pkcs_public_key_free(public_key);
+         silc_server_command_send_status_reply(
+                               cmd, SILC_COMMAND_WATCH,
+                               SILC_STATUS_ERR_NICKNAME_IN_USE, 0);
+         goto out;
+       }
+
+       /* Get the public key from the watcher list and use the same key in
+          new entries as well.  If key doesn't exist then create it. */
+       pkkey = NULL;
+       if (!silc_hash_table_find(server->watcher_list_pk, public_key,
+                                 (void *)&pkkey, NULL))
+         pkkey = public_key;
+       else
+         silc_pkcs_public_key_free(public_key);
+
+       /* Add the client to the watcher list with the specified public
+          key. */
+       silc_hash_table_add(server->watcher_list_pk, pkkey, client);
+
+      } else if (type == 0x01) {
+       /* Delete public key from watch list */
+
+       /* Check that this client is watching this public key */
+       if (silc_hash_table_find_by_context(server->watcher_list_pk,
+                                           public_key, client,
+                                           (void *)&pkkey)) {
+         silc_pkcs_public_key_free(public_key);
+         silc_server_command_send_status_reply(
+                               cmd, SILC_COMMAND_WATCH,
+                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
+         goto out;
+       }
+
+       /* Delete the public key from the watcher list. */
+       silc_hash_table_del_by_context(server->watcher_list_pk,
+                                      public_key, client);
+
+       /* Now check whether there still exists entries with this key, if
+          not then free the key to not leak memory. */
+       if (!silc_hash_table_find(server->watcher_list_pk, hash, NULL, NULL))
+         silc_pkcs_public_key_free(pkkey);
+        silc_pkcs_public_key_free(public_key);
+      }
+
+      pk = silc_argument_get_next_arg(pkargs, &type, &pk_len);
+    }
+  }
+
+  /* Send reply */
+  silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
+                                       SILC_STATUS_OK, 0);
+
   /* Distribute the watch list to backup routers too */
   if (server->backup) {
     SilcBuffer tmpbuf;
+    old_ident = silc_command_get_ident(cmd->payload);
     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
-    silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
+    silc_server_backup_send(server, cmd->sock->user_data, SILC_PACKET_COMMAND,
                            cmd->packet->flags, tmpbuf->data, tmpbuf->len,
                            FALSE, TRUE);
+    silc_command_set_ident(cmd->payload, old_ident);
     silc_buffer_free(tmpbuf);
   }
 
-  silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
-                                       SILC_STATUS_OK, 0);
-
  out:
   silc_free(client_id);
   silc_server_command_free(cmd);
@@ -4178,7 +4409,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
-  unsigned char *username, *auth;
+  unsigned char *username = NULL, *auth;
   SilcUInt32 tmp_len;
   SilcServerConfigAdmin *admin;
   SilcIDListData idata = (SilcIDListData)client;
@@ -4205,6 +4436,16 @@ SILC_SERVER_CMD_FUNC(silcoper)
     goto out;
   }
 
+  /* Check username */
+  username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
+                                  &tmp_len);
+  if (!username) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
+                                         SILC_STATUS_ERR_BAD_USERNAME,
+                                         0);
+    goto out;
+  }
+
   /* Get the admin configuration */
   admin = silc_server_config_find_admin(server, cmd->sock->ip,
                                        username, client->nickname);
@@ -4275,6 +4516,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
                                        SILC_STATUS_OK, 0);
 
  out:
+  silc_free(username);
   silc_server_command_free(cmd);
 }
 
@@ -4380,8 +4622,14 @@ SILC_SERVER_CMD_FUNC(ban)
       }
 
       /* Now add or delete the information. */
-      silc_server_inviteban_process(server, channel->ban_list,
-                                   (SilcUInt8)atype[0], args);
+      if (!silc_server_inviteban_process(server, channel->ban_list,
+                                        (SilcUInt8)atype[0], args)) {
+       silc_server_command_send_status_reply(
+                                     cmd, SILC_COMMAND_BAN,
+                                     SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                     0);
+       goto out;
+      }
     }
     silc_argument_payload_free(args);
   }
@@ -4395,7 +4643,7 @@ SILC_SERVER_CMD_FUNC(ban)
                                          channel->ban_list)),
                       SILC_STR_END);
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
                                              type);
     silc_hash_table_list_reset(&htl);
@@ -4539,7 +4787,7 @@ SILC_SERVER_CMD_FUNC(users)
   unsigned char lc[4];
   SilcUInt32 list_count = 0;
   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
-  char *channel_name;
+  char *channel_name, *channel_namec = NULL;
 
   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
 
@@ -4555,6 +4803,18 @@ SILC_SERVER_CMD_FUNC(users)
     goto out;
   }
 
+  /* Check channel name */
+  if (channel_name) {
+    channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+                                           SILC_STRING_UTF8, 256, NULL);
+    if (!channel_namec) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
+                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
+      goto out;
+    }
+  }
+
+  /* Check Channel ID */
   if (channel_id) {
     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
     if (!id) {
@@ -4572,7 +4832,7 @@ SILC_SERVER_CMD_FUNC(users)
     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
   else
     channel = silc_idlist_find_channel_by_name(server->local_list,
-                                              channel_name, NULL);
+                                              channel_namec, NULL);
 
   if (!channel || (!server->standalone && (channel->disabled ||
                    !channel->users_resolved))) {
@@ -4605,7 +4865,7 @@ SILC_SERVER_CMD_FUNC(users)
       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
     else
       channel = silc_idlist_find_channel_by_name(server->global_list,
-                                                channel_name, NULL);
+                                                channel_namec, NULL);
     if (!channel) {
       /* Channel really does not exist */
       if (id)
@@ -4673,6 +4933,7 @@ SILC_SERVER_CMD_FUNC(users)
   silc_free(id);
 
  out:
+  silc_free(channel_namec);
   silc_server_command_free(cmd);
 }
 
@@ -4946,10 +5207,10 @@ SILC_SERVER_CMD_FUNC(close)
     SILC_GET32_MSB(port, tmp);
 
   server_entry = silc_idlist_find_server_by_conn(server->local_list,
-                                                name, port, FALSE, NULL);
+                                                name, port, TRUE, NULL);
   if (!server_entry)
     server_entry = silc_idlist_find_server_by_conn(server->global_list,
-                                                  name, port, FALSE, NULL);
+                                                  name, port, TRUE, NULL);
   if (!server_entry) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
                                          SILC_STATUS_ERR_NO_SERVER_ID, 0);
@@ -4969,6 +5230,11 @@ SILC_SERVER_CMD_FUNC(close)
   /* Close the connection to the server */
   sock = (SilcSocketConnection)server_entry->connection;
 
+  if (server_entry->server_type == SILC_BACKUP_ROUTER) {
+    server->backup_closed = TRUE;
+    silc_server_backup_del(server, server_entry);
+  }
+
   server->backup_noswitch = TRUE;
   if (server->router == server_entry) {
     server->id_entry->router = NULL;
index 1350aee19ddb515a8a6e549b49f941bb9eeedf07..b4862c61221ed3d38de4bd46891c810400405ceb 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -147,6 +147,12 @@ silc_server_command_process_error(SilcServerCommandReplyContext cmd,
        client = silc_idlist_find_client_by_id(server->global_list,
                                               client_id, FALSE, NULL);
        if (client) {
+
+         if (client->data.public_key)
+           silc_hash_table_del_by_context(server->pk_hash,
+                                           client->data.public_key,
+                                           client);
+
          silc_server_remove_from_channels(server, NULL, client, TRUE,
                                           NULL, TRUE, FALSE);
          silc_idlist_del_data(client);
@@ -164,14 +170,14 @@ static char
 silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 {
   SilcServer server = cmd->server;
-  unsigned char *tmp, *id_data, *umodes;
-  char *nickname, *username, *realname, *servername = NULL;
+  unsigned char *id_data, *umodes;
+  char *nickname, *username, *realname, *tmp, *servername = NULL;
   unsigned char *fingerprint;
   SilcClientID *client_id;
   SilcClientEntry client;
   SilcIDCacheEntry cache = NULL;
   char global = FALSE;
-  char *nick;
+  char *nick = NULL;
   SilcUInt32 mode = 0, len, len2, id_len, flen;
 
   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
@@ -212,13 +218,14 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 
     /* We don't have that client anywhere, add it. The client is added
        to global list since server didn't have it in the lists so it must be
-       global. */
-    client = silc_idlist_add_client(server->global_list, nick,
-                                   strdup(username),
+       global. This will check for valid nickname and username strings. */
+    client = silc_idlist_add_client(server->global_list, nick, username,
                                    strdup(realname), client_id,
                                    cmd->sock->user_data, NULL, 0);
     if (!client) {
       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+      silc_free(nick);
+      silc_free(servername);
       return FALSE;
     }
 
@@ -232,8 +239,31 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 
     SILC_LOG_DEBUG(("Updating client data"));
 
-    /* Take hostname out of nick string if it includes it. */
+    /* Check nickname */
     silc_parse_userfqdn(nickname, &nick, &servername);
+    nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+                                    128, NULL);
+    if (!nickname) {
+      SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOIS reply "
+                     "from %s",
+                     cmd->sock->hostname ? cmd->sock->hostname : "", nick));
+      silc_free(nick);
+      silc_free(servername);
+      return FALSE;
+    }
+
+    /* Check username */
+    silc_parse_userfqdn(username, &tmp, NULL);
+    if (!silc_identifier_verify(tmp, strlen(tmp), SILC_STRING_UTF8, 128)) {
+      silc_free(tmp);
+      silc_free(nick);
+      silc_free(servername);
+      SILC_LOG_ERROR(("Malformed username '%s' received in WHOIS reply "
+                     "from %s",
+                     cmd->sock->hostname ? cmd->sock->hostname : "", tmp));
+      return FALSE;
+    }
+    silc_free(tmp);
 
     /* Remove the old cache entry  */
     silc_idcache_del_by_context(global ? server->global_list->clients :
@@ -254,7 +284,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 
     /* Create new cache entry */
     silc_idcache_add(global ? server->global_list->clients :
-                    server->local_list->clients, nick, client->id,
+                    server->local_list->clients, nickname, client->id,
                     client, 0, NULL);
     silc_free(client_id);
   }
@@ -294,6 +324,68 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     silc_free(client->attrs);
     client->attrs = silc_memdup(tmp, len);
     client->attrs_len = len;
+
+    /* Try to take public key from attributes if present and we don't have
+       the key already.  Do this only on normal server.  Routers do GETKEY
+       for all clients anyway. */
+    if (server->server_type != SILC_ROUTER && !client->data.public_key) {
+      SilcAttributePayload attr;
+      SilcAttributeObjPk pk;
+      unsigned char f[20];
+      SilcDList attrs = silc_attribute_payload_parse(tmp, len);
+
+      SILC_LOG_DEBUG(("Take client public key from attributes"));
+
+      if (attrs) {
+       silc_dlist_start(attrs);
+       while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
+         if (silc_attribute_get_attribute(attr) ==
+             SILC_ATTRIBUTE_USER_PUBLIC_KEY) {
+
+           if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
+             continue;
+
+           /* Take only SILC public keys */
+           if (strcmp(pk.type, "silc-rsa")) {
+             silc_free(pk.type);
+             silc_free(pk.data);
+             continue;
+           }
+
+           /* Verify that the server provided fingerprint matches the key */
+           silc_hash_make(server->sha1hash, pk.data, pk.data_len, f);
+           if (memcmp(f, client->data.fingerprint, sizeof(f))) {
+             silc_free(pk.type);
+             silc_free(pk.data);
+             continue;
+           }
+
+           /* Save the public key. */
+           if (!silc_pkcs_public_key_decode(pk.data, pk.data_len,
+                                            &client->data.public_key)) {
+             silc_free(pk.type);
+             silc_free(pk.data);
+             continue;
+           }
+
+           SILC_LOG_DEBUG(("Saved client public key from attributes"));
+
+           /* Add to public key hash table */
+           if (!silc_hash_table_find_by_context(server->pk_hash,
+                                                client->data.public_key,
+                                                client, NULL))
+             silc_hash_table_add(server->pk_hash,
+                                 client->data.public_key, client);
+
+           silc_free(pk.type);
+           silc_free(pk.data);
+           break;
+         }
+       }
+
+       silc_attribute_payload_list_free(attrs);
+      }
+    }
   }
 
   return TRUE;
@@ -368,11 +460,11 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
   SilcServer server = cmd->server;
   SilcUInt32 len, id_len;
   unsigned char *id_data;
-  char *nickname, *username, *realname, *servername = NULL;
+  char *nickname, *username, *realname, *servername = NULL, *tmp;
   SilcClientID *client_id;
   SilcClientEntry client;
   SilcIDCacheEntry cache = NULL;
-  char *nick;
+  char *nick = NULL;
   int global = FALSE;
 
   id_data = silc_argument_get_arg_type(cmd->args, 2, &id_len);
@@ -409,13 +501,15 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
     /* We don't have that client anywhere, add it. The client is added
        to global list since server didn't have it in the lists so it must be
        global. */
-    client = silc_idlist_add_client(server->global_list, nick,
-                                   strdup(username), strdup(realname),
+    client = silc_idlist_add_client(server->global_list, nick, username,
+                                   strdup(realname),
                                    silc_id_dup(client_id, SILC_ID_CLIENT),
                                    cmd->sock->user_data, NULL,
                                    SILC_ID_CACHE_EXPIRE_DEF);
     if (!client) {
       SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+      silc_free(nick);
+      silc_free(servername);
       return FALSE;
     }
 
@@ -426,8 +520,31 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
   } else {
     /* We have the client already, update the data */
 
-    /* Take hostname out of nick string if it includes it. */
+    /* Check nickname */
     silc_parse_userfqdn(nickname, &nick, &servername);
+    nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+                                    128, NULL);
+    if (!nickname) {
+      SILC_LOG_ERROR(("Malformed nickname '%s' received in WHOWAS reply "
+                     "from %s",
+                     cmd->sock->hostname ? cmd->sock->hostname : "", nick));
+      silc_free(nick);
+      silc_free(servername);
+      return FALSE;
+    }
+
+    /* Check username */
+    silc_parse_userfqdn(username, &tmp, NULL);
+    if (!silc_identifier_verify(tmp, strlen(tmp), SILC_STRING_UTF8, 128)) {
+      silc_free(tmp);
+      silc_free(nick);
+      silc_free(servername);
+      SILC_LOG_ERROR(("Malformed username '%s' received in WHOWAS reply "
+                     "from %s",
+                     cmd->sock->hostname ? cmd->sock->hostname : "", tmp));
+      return FALSE;
+    }
+    silc_free(tmp);
 
     silc_free(client->nickname);
     silc_free(client->username);
@@ -443,7 +560,7 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
     silc_idcache_del_by_context(global ? server->global_list->clients :
                                server->local_list->clients, client);
     silc_idcache_add(global ? server->global_list->clients :
-                    server->local_list->clients, nick, client->id,
+                    server->local_list->clients, nickname, client->id,
                     client, 0, NULL);
   }
 
@@ -555,14 +672,15 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       /* We don't have that client anywhere, add it. The client is added
         to global list since server didn't have it in the lists so it must be
         global. */
-      client = silc_idlist_add_client(server->global_list, nick,
-                                     info ? strdup(info) : NULL, NULL,
+      client = silc_idlist_add_client(server->global_list, nick, info, NULL,
                                      client_id, cmd->sock->user_data,
                                      NULL, time(NULL) + 300);
       if (!client) {
        SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+       silc_free(nick);
        goto error;
       }
+
       client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
@@ -575,12 +693,28 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       if (name) {
        silc_parse_userfqdn(name, &nick, NULL);
 
+       /* Check nickname */
+       name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+                                    128, NULL);
+       if (!name) {
+         SILC_LOG_ERROR(("Malformed nickname '%s' received in IDENTIFY reply "
+                         "from %s",
+                         cmd->sock->hostname ?
+                         cmd->sock->hostname : "", nick));
+         return FALSE;
+       }
+
        /* Remove the old cache entry */
        silc_idcache_del_by_context(global ? server->global_list->clients :
                                    server->local_list->clients, client);
 
        silc_free(client->nickname);
        client->nickname = nick;
+
+       /* Add new cache entry */
+       silc_idcache_add(global ? server->global_list->clients :
+                        server->local_list->clients, name, client->id,
+                        client, expire, NULL);
       }
 
       if (info) {
@@ -591,13 +725,6 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
       client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
 
-      if (name) {
-       /* Add new cache entry */
-       silc_idcache_add(global ? server->global_list->clients :
-                        server->local_list->clients, nick, client->id,
-                        client, expire, NULL);
-      }
-
       /* If client is global and is not on any channel then add that we'll
          expire the entry after a while. */
       if (global && server->server_type == SILC_SERVER) {
@@ -664,16 +791,24 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
 
     SILC_LOG_DEBUG(("Received channel information"));
 
+    /* Check channel name */
+    info = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
+                                  256, NULL);
+    if (!info)
+      goto error;
+
     channel = silc_idlist_find_channel_by_name(server->local_list,
-                                              name, NULL);
+                                              info, NULL);
     if (!channel)
       channel = silc_idlist_find_channel_by_name(server->global_list,
-                                                name, NULL);
+                                                info, NULL);
     if (!channel) {
       /* If router did not find such Channel ID in its lists then this must
         be bogus channel or some router in the net is buggy. */
-      if (server->server_type != SILC_SERVER)
+      if (server->server_type != SILC_SERVER) {
+       silc_free(info);
        goto error;
+      }
 
       /* We don't have that channel anywhere, add it. */
       channel = silc_idlist_add_channel(server->global_list, strdup(name),
@@ -681,8 +816,10 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
                                        server->router, NULL, NULL, 0);
       if (!channel) {
        silc_free(channel_id);
+       silc_free(info);
        goto error;
       }
+      silc_free(info);
       channel_id = NULL;
     }
 
@@ -755,7 +892,7 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
 
   /* Get the name */
   name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
-  if (tmp_len > 256)
+  if (!name)
     goto out;
 
   entry = silc_idlist_find_server_by_id(server->local_list, server_id,
@@ -766,7 +903,7 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
     if (!entry) {
       /* Add the server to global list */
       server_id = silc_id_dup(server_id, SILC_ID_SERVER);
-      entry = silc_idlist_add_server(server->global_list, name, 0,
+      entry = silc_idlist_add_server(server->global_list, strdup(name), 0,
                                     server_id, cmd->sock->user_data,
                                     cmd->sock);
       if (!entry) {
@@ -817,8 +954,32 @@ SILC_SERVER_CMD_REPLY_FUNC(motd)
   if (!entry) {
     entry = silc_idlist_find_server_by_id(server->global_list, server_id,
                                          TRUE, NULL);
-    if (!entry)
-      goto out;
+    if (!entry) {
+      SilcBuffer buffer;
+
+      /* If router did not find such Server ID in its lists then this must
+        be bogus client or some router in the net is buggy. */
+      if (server->server_type != SILC_SERVER)
+       goto out;
+
+      /* entry isn't known so we IDENTIFY it. otherwise the
+         silc_server_command_motd won't know about it and tell
+         the client that there is no such server */
+      buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
+                                             ++server->cmd_ident, 5,
+                                             1, NULL, 0, 2, NULL, 0,
+                                             3, NULL, 0, 4, NULL, 0,
+                                             5, tmp, tmp_len);
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+                             SILC_PACKET_COMMAND, 0, buffer->data,
+                             buffer->len, TRUE);
+      silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
+                                 server->cmd_ident,
+                                 silc_server_command_reply_motd,
+                                 cmd);
+      silc_buffer_free(buffer);
+      return;
+    }
   }
 
   /* Get the motd */
@@ -853,7 +1014,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   SilcHmac hmac = NULL;
   SilcUInt32 id_len, len, list_count;
   unsigned char *id_string;
-  char *channel_name, *tmp;
+  char *channel_name, *channel_namec = NULL, *tmp;
   SilcUInt32 mode, created;
   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
   SilcPublicKey founder_key = NULL;
@@ -942,8 +1103,12 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
 
   /* See whether we already have the channel. */
+  channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+                                         SILC_STRING_UTF8, 256, NULL);
+  if (!channel_namec)
+    goto out;
   entry = silc_idlist_find_channel_by_name(server->local_list,
-                                          channel_name, &cache);
+                                          channel_namec, &cache);
   if (!entry) {
     /* Add new channel */
 
@@ -954,7 +1119,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
     /* If the channel is found from global list we must move it to the
        local list. */
     entry = silc_idlist_find_channel_by_name(server->global_list,
-                                            channel_name, &cache);
+                                            channel_namec, &cache);
     if (entry)
       silc_idlist_del_channel(server->global_list, entry);
 
@@ -1054,6 +1219,11 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
   if (tmp && server->server_type == SILC_SERVER)
     silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
 
+  /* The the user limit */
+  tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
+  if (tmp && len == 4)
+    SILC_GET32_MSB(entry->user_limit, tmp);
+
   /* If channel was not created we know there is global users on the
      channel. */
   entry->global_users = (created == 0 ? TRUE : FALSE);
@@ -1084,6 +1254,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
  err:
+  silc_free(channel_namec);
   if (hmac)
     silc_hmac_free(hmac);
   silc_free(client_id);
@@ -1277,8 +1448,14 @@ SILC_SERVER_CMD_REPLY_FUNC(getkey)
        goto out;
     }
 
-    client->data.public_key = public_key;
-    public_key = NULL;
+    if (!client->data.public_key) {
+      if (!silc_hash_table_find_by_context(server->pk_hash, public_key,
+                                          client, NULL))
+       silc_hash_table_add(server->pk_hash, public_key, client);
+
+      client->data.public_key = public_key;
+      public_key = NULL;
+    }
   } else if (id_type == SILC_ID_SERVER) {
     server_id = silc_id_payload_get_id(idp);
 
@@ -1318,13 +1495,15 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
   SilcChannelEntry channel;
   SilcIDCacheEntry cache;
   SilcUInt32 len;
-  unsigned char *tmp, *name, *topic;
+  unsigned char *tmp, *name, *namec = NULL, *topic;
   SilcUInt32 usercount = 0;
   bool global_list = FALSE;
 
   COMMAND_CHECK_STATUS;
 
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+  if (!tmp)
+    goto out;
   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
   if (!channel_id)
     goto out;
@@ -1335,12 +1514,17 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
   if (tmp)
     SILC_GET32_MSB(usercount, tmp);
 
+  namec = silc_channel_name_check(name, strlen(name), SILC_STRING_UTF8,
+                                 256, NULL);
+  if (!namec)
+    goto out;
+
   /* Add the channel entry if we do not have it already */
   channel = silc_idlist_find_channel_by_name(server->local_list,
-                                            name, &cache);
+                                            namec, &cache);
   if (!channel) {
     channel = silc_idlist_find_channel_by_name(server->global_list,
-                                              name, &cache);
+                                              namec, &cache);
     global_list = TRUE;
   }
   if (!channel) {
@@ -1384,6 +1568,7 @@ SILC_SERVER_CMD_REPLY_FUNC(list)
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_LIST);
   silc_free(channel_id);
  err:
+  silc_free(namec);
   silc_server_command_reply_free(cmd);
 }
 
index 2562c0f03d39ec1db2f4c252dd78a0fc9d0c0e38..621c4c4ffccc8600c8db86416e5c3bf5b9b7c40c 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -119,9 +119,18 @@ silc_idlist_add_server(SilcIDList id_list,
                       void *connection)
 {
   SilcServerEntry server;
+  char *server_namec = NULL;
 
   SILC_LOG_DEBUG(("Adding new server entry"));
 
+  /* Normalize name.  This is cached, original is in server context.  */
+  if (server_name) {
+    server_namec = silc_identifier_check(server_name, strlen(server_name),
+                                        SILC_STRING_UTF8, 256, NULL);
+    if (!server_namec)
+      return NULL;
+  }
+
   server = silc_calloc(1, sizeof(*server));
   server->server_name = server_name;
   server->server_type = server_type;
@@ -129,9 +138,10 @@ silc_idlist_add_server(SilcIDList id_list,
   server->router = router;
   server->connection = connection;
 
-  if (!silc_idcache_add(id_list->servers, server->server_name,
+  if (!silc_idcache_add(id_list->servers, server_namec,
                        (void *)server->id, (void *)server, 0, NULL)) {
     silc_free(server);
+    silc_free(server_namec);
     return NULL;
   }
 
@@ -171,7 +181,7 @@ silc_idlist_find_server_by_id(SilcIDList id_list, SilcServerID *id,
   return server;
 }
 
-/* Find server by name */
+/* Find server by name.  The 'name' must be normalized already. */
 
 SilcServerEntry
 silc_idlist_find_server_by_name(SilcIDList id_list, char *name,
@@ -259,6 +269,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
 {
   SilcIDCacheEntry id_cache = NULL;
   SilcServerEntry server;
+  char *name;
 
   if (!old_id || !new_id)
     return NULL;
@@ -270,6 +281,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
     return NULL;
 
   server = (SilcServerEntry)id_cache->context;
+  name = strdup(id_cache->name);
 
   /* Remove the old entry and add a new one */
 
@@ -278,8 +290,7 @@ silc_idlist_replace_server_id(SilcIDList id_list, SilcServerID *old_id,
   silc_free(server->id);
   server->id = new_id;
 
-  silc_idcache_add(id_list->servers, server->server_name, server->id,
-                  server, 0, NULL);
+  silc_idcache_add(id_list->servers, name, server->id, server, 0, NULL);
 
   SILC_LOG_DEBUG(("Found"));
 
@@ -337,12 +348,39 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
                       int expire)
 {
   SilcClientEntry client;
+  char *nicknamec = NULL;
 
   SILC_LOG_DEBUG(("Adding new client entry"));
 
+  /* Normalize name.  This is cached, original is in client context.  */
+  if (nickname) {
+    nicknamec = silc_identifier_check(nickname, strlen(nickname),
+                                     SILC_STRING_UTF8, 128, NULL);
+    if (!nicknamec)
+      return NULL;
+  }
+
+  /* Check username. */
+  if (username) {
+    char *u = NULL, *h = NULL;
+    silc_parse_userfqdn(username, &u, &h);
+    if (!u)
+      return NULL;
+    if (!silc_identifier_verify(u, strlen(u), SILC_STRING_UTF8, 128)) {
+      silc_free(u);
+      silc_free(h);
+      return NULL;
+    }
+    if (h && !silc_identifier_verify(h, strlen(h), SILC_STRING_UTF8, 256)) {
+      silc_free(u);
+      silc_free(h);
+      return NULL;
+    }
+  }
+
   client = silc_calloc(1, sizeof(*client));
   client->nickname = nickname;
-  client->username = username;
+  client->username = username ? strdup(username) : NULL;
   client->userinfo = userinfo;
   client->id = id;
   client->router = router;
@@ -350,10 +388,11 @@ silc_idlist_add_client(SilcIDList id_list, char *nickname, char *username,
   client->channels = silc_hash_table_alloc(3, silc_hash_ptr, NULL,
                                           NULL, NULL, NULL, NULL, TRUE);
 
-  if (!silc_idcache_add(id_list->clients, nickname, (void *)client->id,
+  if (!silc_idcache_add(id_list->clients, nicknamec, (void *)client->id,
                        (void *)client, expire, NULL)) {
     silc_hash_table_free(client->channels);
     silc_free(client);
+    silc_free(nicknamec);
     return NULL;
   }
 
@@ -368,7 +407,7 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
   SILC_LOG_DEBUG(("Start"));
 
   if (entry) {
-    /* Remove from cache */
+    /* Remove from cache. Destructor callback deletes stuff. */
     if (!silc_idcache_del_by_context(id_list->clients, entry)) {
       SILC_LOG_DEBUG(("Unknown client, did not delete"));
       return FALSE;
@@ -376,7 +415,6 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
 
     assert(!silc_hash_table_count(entry->channels));
 
-    /* Free data */
     silc_free(entry->nickname);
     silc_free(entry->servername);
     silc_free(entry->username);
@@ -394,8 +432,32 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
   return FALSE;
 }
 
+/* ID Cache destructor */
+
+void silc_idlist_client_destructor(SilcIDCache cache,
+                                  SilcIDCacheEntry entry)
+{
+  SilcClientEntry client;
+
+  client = (SilcClientEntry)entry->context;
+  if (client) {
+    assert(!silc_hash_table_count(client->channels));
+    silc_free(client->nickname);
+    silc_free(client->servername);
+    silc_free(client->username);
+    silc_free(client->userinfo);
+    silc_free(client->id);
+    silc_free(client->attrs);
+    silc_hash_table_free(client->channels);
+
+    memset(client, 'A', sizeof(*client));
+    silc_free(client);
+  }
+}
+
 /* Returns all clients matching requested nickname. Number of clients is
-   returned to `clients_count'. Caller must free the returned table. */
+   returned to `clients_count'. Caller must free the returned table.
+   The 'nickname' must be normalized already. */
 
 int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
                                        char *server,
@@ -419,7 +481,6 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
 
   while (silc_idcache_list_next(list, &id_cache))
     (*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context;
-
   silc_idcache_list_free(list);
 
   SILC_LOG_DEBUG(("Found total %d clients", *clients_count));
@@ -428,7 +489,8 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
 }
 
 /* Returns all clients matching requested nickname hash. Number of clients
-   is returned to `clients_count'. Caller must free the returned table. */
+   is returned to `clients_count'. Caller must free the returned table.
+   The 'nickname' must be normalized already. */
 
 int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
                                    SilcHash md5hash,
@@ -439,13 +501,10 @@ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
   SilcIDCacheEntry id_cache = NULL;
   unsigned char hash[32];
   SilcClientID client_id;
-  char nick[128 + 1];
 
   SILC_LOG_DEBUG(("Start"));
 
-  memset(nick, 0, sizeof(nick));
-  silc_to_lower(nickname, nick, sizeof(nick) - 1);
-  silc_hash_make(md5hash, nick, strlen(nick), hash);
+  silc_hash_make(md5hash, nickname, strlen(nickname), hash);
 
   /* As the Client ID is hashed in the ID cache by hashing only the hash
      from the Client ID, we can do a lookup with only the hash not the
@@ -521,12 +580,21 @@ silc_idlist_replace_client_id(SilcServer server,
 {
   SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry client;
+  char *nicknamec = NULL;
 
   if (!old_id || !new_id)
     return NULL;
 
   SILC_LOG_DEBUG(("Replacing Client ID"));
 
+  /* Normalize name. This is cached, original is in client context.  */
+  if (nickname) {
+    nicknamec = silc_identifier_check(nickname, strlen(nickname),
+                                     SILC_STRING_UTF8, 128, NULL);
+    if (!nicknamec)
+      return NULL;
+  }
+
   /* Do extended search since the normal ID comparison function for
      Client ID's compares only the hash from the Client ID and not the
      entire ID. The silc_hash_client_id_compare compares the entire
@@ -559,7 +627,7 @@ silc_idlist_replace_client_id(SilcServer server,
     silc_server_check_watcher_list(server, client, nickname,
                                   SILC_NOTIFY_TYPE_NICK_CHANGE);
 
-  if (!silc_idcache_add(id_list->clients, client->nickname, client->id,
+  if (!silc_idcache_add(id_list->clients, nicknamec, client->id,
                        client, 0, NULL))
     return NULL;
 
@@ -568,27 +636,6 @@ silc_idlist_replace_client_id(SilcServer server,
   return client;
 }
 
-/* Client cache entry destructor that is called when the cache is purged. */
-
-void silc_idlist_client_destructor(SilcIDCache cache,
-                                  SilcIDCacheEntry entry)
-{
-  SilcClientEntry client;
-
-  client = (SilcClientEntry)entry->context;
-  if (client) {
-    assert(!silc_hash_table_count(client->channels));
-    silc_free(client->nickname);
-    silc_free(client->username);
-    silc_free(client->userinfo);
-    silc_free(client->id);
-    silc_free(client->attrs);
-    silc_hash_table_free(client->channels);
-
-    memset(client, 'A', sizeof(*client));
-    silc_free(client);
-  }
-}
 
 /******************************************************************************
 
@@ -606,9 +653,18 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
                        int expire)
 {
   SilcChannelEntry channel;
+  char *channel_namec = NULL;
 
   SILC_LOG_DEBUG(("Adding new channel %s", channel_name));
 
+  /* Normalize name.  This is cached, original is in client context.  */
+  if (channel_name) {
+    channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+                                           SILC_STRING_UTF8, 256, NULL);
+    if (!channel_namec)
+      return NULL;
+  }
+
   channel = silc_calloc(1, sizeof(*channel));
   channel->channel_name = channel_name;
   channel->mode = mode;
@@ -626,11 +682,12 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
   channel->user_list = silc_hash_table_alloc(3, silc_hash_ptr, NULL, NULL,
                                             NULL, NULL, NULL, TRUE);
 
-  if (!silc_idcache_add(id_list->channels, channel->channel_name,
+  if (!silc_idcache_add(id_list->channels, channel_namec,
                        (void *)channel->id, (void *)channel, expire, NULL)) {
     silc_hmac_free(channel->hmac);
     silc_hash_table_free(channel->user_list);
     silc_free(channel);
+    silc_free(channel_namec);
     return NULL;
   }
 
@@ -710,7 +767,7 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
 }
 
 /* Finds channel by channel name. Channel names are unique and they
-   are not case-sensitive. */
+   are not case-sensitive.  The 'name' must be normalized already. */
 
 SilcChannelEntry
 silc_idlist_find_channel_by_name(SilcIDList id_list, char *name,
@@ -774,6 +831,7 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
 {
   SilcIDCacheEntry id_cache = NULL;
   SilcChannelEntry channel;
+  char *name;
 
   if (!old_id || !new_id)
     return NULL;
@@ -785,6 +843,7 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
     return NULL;
 
   channel = (SilcChannelEntry)id_cache->context;
+  name = strdup(id_cache->name);
 
   /* Remove the old entry and add a new one */
 
@@ -793,8 +852,7 @@ silc_idlist_replace_channel_id(SilcIDList id_list, SilcChannelID *old_id,
   silc_free(channel->id);
   channel->id = new_id;
 
-  silc_idcache_add(id_list->channels, channel->channel_name, channel->id,
-                  channel, 0, NULL);
+  silc_idcache_add(id_list->channels, name, channel->id, channel, 0, NULL);
 
   SILC_LOG_DEBUG(("Replaced"));
 
index cfb46feaddf2847f56cea06e3aba6296646dfbd1..cff9c43c161f1dc219339e142bd48e2fbc6c99ba 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -244,7 +244,10 @@ typedef struct SilcChannelClientEntryStruct {
 
    unsigned char *nickname
 
-       The nickname of the client.
+       The nickname of the client.  This is nickname in original format,
+       not casefolded or normalized.  However, it is checked to assure
+       that prohibited characters do not exist.  The casefolded version
+       is in the ID Cache.
 
    char *servername
 
@@ -366,6 +369,10 @@ struct SilcClientEntryStruct {
   /* data.status is RESOLVING and this includes the resolving command
      reply identifier. */
   SilcUInt16 resolve_cmd_ident;
+
+  /* we need this so nobody can resume more than once at the same time -
+   * server crashes, really odd behaviour, ... */
+  SilcClientEntry resuming_client;
 };
 
 /*
@@ -388,7 +395,10 @@ struct SilcClientEntryStruct {
 
    char *channel_name
 
-       Logical name of the channel.
+       Logical name of the channel.  This is the original format, not
+       the casefolded or normalized.  However, this is checked to assure
+       that prohibited characters do not exist.  The casefolded version
+       is in the ID Cache.
 
    SilcUInt32 mode
 
index b9a0224f052f99174af426457632390cdc458960..fa24ff21e4f1af12ef652e0c7d49d049c7d51a82 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -227,13 +227,16 @@ void silc_server_notify(SilcServer server,
 
     if (server->server_type != SILC_ROUTER ||
        sock->type == SILC_SOCKET_TYPE_ROUTER) {
-      /* If this is the first one on the channel then it is the founder of
-        the channel. This is done on normal server and on router if this
-        notify is coming from router */
-      if (!silc_hash_table_count(channel->user_list)) {
-       SILC_LOG_DEBUG(("Client %s is founder on channel",
-                       silc_id_render(chl->client->id, SILC_ID_CLIENT)));
-       chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+      /* If founder auth is set, first client is not automatically founder. */
+      if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
+       /* If this is the first one on the channel then it is the founder of
+          the channel. This is done on normal server and on router if this
+          notify is coming from router */
+       if (!silc_hash_table_count(channel->user_list)) {
+         SILC_LOG_DEBUG(("Client %s is founder on channel",
+                         silc_id_render(chl->client->id, SILC_ID_CLIENT)));
+         chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+       }
       }
     }
 
@@ -361,6 +364,11 @@ void silc_server_notify(SilcServer server,
     SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
     silc_schedule_task_del_by_context(server->schedule, client);
 
+    /* Remove from public key hash table. */
+    if (client->data.public_key)
+      silc_hash_table_del_by_context(server->pk_hash, client->data.public_key,
+                                     client);
+
     /* Remove the client from all channels. */
     silc_server_remove_from_channels(server, NULL, client, TRUE,
                                     tmp, FALSE, FALSE);
@@ -374,6 +382,9 @@ void silc_server_notify(SilcServer server,
     silc_server_del_from_watcher_list(server, client);
 
     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+    client->mode = 0;
+    client->router = NULL;
+    client->connection = NULL;
     cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
     break;
 
@@ -623,7 +634,7 @@ void silc_server_notify(SilcServer server,
          mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
        SilcBuffer chpklist;
        SilcBuffer sidp;
-       unsigned char mask[4];
+       unsigned char mask[4], ulimit[4];
 
        SILC_LOG_DEBUG(("Channel public key list received from router"));
        tmp = silc_argument_get_arg_type(args, 7, &tmp_len);
@@ -639,8 +650,10 @@ void silc_server_notify(SilcServer server,
          break;
        sidp = silc_id_payload_encode(server->router->id, SILC_ID_SERVER);
        SILC_PUT32_MSB(channel->mode, mask);
+       if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
+         SILC_PUT32_MSB(channel->user_limit, ulimit);
        silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
-                                          SILC_NOTIFY_TYPE_CMODE_CHANGE, 7,
+                                          SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
                                           sidp->data, sidp->len,
                                           mask, 4,
                                           channel->cipher,
@@ -653,7 +666,13 @@ void silc_server_notify(SilcServer server,
                                           channel->passphrase ?
                                           strlen(channel->passphrase) : 0,
                                           NULL, 0,
-                                          chpklist->data, chpklist->len);
+                                          chpklist->data, chpklist->len,
+                                          (channel->mode &
+                                           SILC_CHANNEL_MODE_ULIMIT ?
+                                           ulimit : NULL),
+                                          (channel->mode &
+                                           SILC_CHANNEL_MODE_ULIMIT ?
+                                           sizeof(ulimit) : 0));
        silc_buffer_free(sidp);
        silc_buffer_free(chpklist);
        goto out;
@@ -762,6 +781,7 @@ void silc_server_notify(SilcServer server,
       if (channel->founder_key)
        silc_pkcs_public_key_free(channel->founder_key);
       channel->founder_key = NULL;
+      SILC_LOG_DEBUG(("Founder public key received"));
       if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len,
                                               &channel->founder_key)) {
        SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
@@ -808,6 +828,11 @@ void silc_server_notify(SilcServer server,
       }
     }
 
+    /* Get the user limit */
+    tmp = silc_argument_get_arg_type(args, 8, &tmp_len);
+    if (tmp && tmp_len == 4 && mode & SILC_CHANNEL_MODE_ULIMIT)
+      SILC_GET32_MSB(channel->user_limit, tmp);
+
     /* Send the same notify to the channel */
     silc_server_packet_send_to_channel(server, NULL, channel, packet->type,
                                       FALSE, TRUE, packet->buffer->data,
@@ -975,8 +1000,9 @@ void silc_server_notify(SilcServer server,
        /* Get the founder of the channel and if found then this client
           cannot be the founder since there already is one. */
        silc_hash_table_list(channel->user_list, &htl);
-       while (silc_hash_table_get(&htl, NULL, (void **)&chl2))
+       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
          if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
+           SILC_LOG_DEBUG(("Founder already on channel"));
            chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
            silc_server_force_cumode_change(server, sock, channel,
                                            chl, mode);
@@ -987,7 +1013,7 @@ void silc_server_notify(SilcServer server,
        if (!(mode & SILC_CHANNEL_UMODE_CHANFO))
          break;
 
-       /* Founder not found of the channel.  Since the founder auth mode
+       /* Founder not found on the channel.  Since the founder auth mode
           is set on the channel now check whether this is the client that
           originally set the mode. */
 
@@ -997,6 +1023,7 @@ void silc_server_notify(SilcServer server,
          if (!tmp || !silc_pkcs_public_key_payload_decode(tmp, tmp_len,
                                                           &founder_key)) {
            chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           SILC_LOG_DEBUG(("Founder public key not present"));
            silc_server_force_cumode_change(server, sock, channel, chl, mode);
            notify_sent = TRUE;
            break;
@@ -1007,6 +1034,7 @@ void silc_server_notify(SilcServer server,
          if (!silc_pkcs_public_key_compare(channel->founder_key,
                                            founder_key)) {
            chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           SILC_LOG_DEBUG(("Founder public key mismatch"));
            silc_server_force_cumode_change(server, sock, channel, chl, mode);
            notify_sent = TRUE;
            break;
@@ -1015,11 +1043,13 @@ void silc_server_notify(SilcServer server,
 
        /* There cannot be anyone else as founder on the channel now.  This
           client is definitely the founder due to this 'authentication'.
-          We trust the server did the actual authentication earlier. */
+          We trust the server did the actual signature verification
+          earlier (bad, yes). */
        silc_hash_table_list(channel->user_list, &htl);
        while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
          if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
            chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           SILC_LOG_DEBUG(("Removing old founder rights, new authenticated"));
            silc_server_force_cumode_change(server, NULL, channel, chl2,
                                            chl2->mode);
            break;
@@ -1044,7 +1074,7 @@ void silc_server_notify(SilcServer server,
 
       /* Send the same notify to the channel */
       if (!notify_sent)
-       silc_server_packet_send_to_channel(server, NULL, channel,
+       silc_server_packet_send_to_channel(server, sock, channel,
                                           packet->type,
                                           FALSE, TRUE, packet->buffer->data,
                                           packet->buffer->len, FALSE);
@@ -1138,15 +1168,16 @@ void silc_server_notify(SilcServer server,
       if (!iargs)
        goto out;
 
-      if (action != 0x01 && !channel->invite_list)
+      if (!channel->invite_list)
        channel->invite_list =
          silc_hash_table_alloc(0, silc_hash_ptr,
                                NULL, NULL, NULL,
                                silc_server_inviteban_destruct, channel, TRUE);
 
       /* Proces the invite action */
-      silc_server_inviteban_process(server, channel->invite_list, action,
-                                   iargs);
+      if (!silc_server_inviteban_process(server, channel->invite_list, action,
+                                        iargs))
+       goto out;
       silc_argument_payload_free(iargs);
 
       /* If we are router we must send this notify to our local servers on
@@ -1360,6 +1391,12 @@ void silc_server_notify(SilcServer server,
            if (local)
              silc_server_del_from_watcher_list(server, client);
 
+           /* Remove from public key hash table. */
+           if (client->data.public_key)
+             silc_hash_table_del_by_context(server->pk_hash,
+                                             client->data.public_key,
+                                             client);
+
            /* Remove the client */
            silc_idlist_del_data(client);
            silc_idlist_del_client(local ? server->local_list :
@@ -1604,8 +1641,15 @@ void silc_server_notify(SilcServer server,
                                       FALSE, TRUE);
 
       /* Check if anyone is watching this nickname */
-      silc_server_check_watcher_list(server, client, NULL,
-                                    SILC_NOTIFY_TYPE_KILLED);
+      if (server->server_type == SILC_ROUTER)
+       silc_server_check_watcher_list(server, client, NULL,
+                                      SILC_NOTIFY_TYPE_KILLED);
+
+      /* Remove from public key hash table. */
+      if (client->data.public_key)
+       silc_hash_table_del_by_context(server->pk_hash,
+                                      client->data.public_key,
+                                      client);
 
       /* Update statistics */
       server->stat.clients--;
@@ -1622,6 +1666,9 @@ void silc_server_notify(SilcServer server,
       }
 
       client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+      client->mode = 0;
+      client->router = NULL;
+      client->connection = NULL;
       cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
       break;
     }
@@ -1741,15 +1788,16 @@ void silc_server_notify(SilcServer server,
       if (!iargs)
        goto out;
 
-      if (action != 0x01 && !channel->ban_list)
+      if (!channel->ban_list)
        channel->ban_list =
          silc_hash_table_alloc(0, silc_hash_ptr,
                                NULL, NULL, NULL,
                                silc_server_inviteban_destruct, channel, TRUE);
 
       /* Proces the ban action */
-      silc_server_inviteban_process(server, channel->ban_list, action,
-                                   iargs);
+      if (!silc_server_inviteban_process(server, channel->ban_list, action,
+                                        iargs))
+       goto out;
       silc_argument_payload_free(iargs);
 
       /* If we are router we must send this notify to our local servers on
@@ -1789,6 +1837,11 @@ void silc_server_notify(SilcServer server,
          client = silc_idlist_find_client_by_id(server->global_list,
                                                 client_id, FALSE, NULL);
          if (client) {
+           if (client->data.public_key)
+             silc_hash_table_del_by_context(server->pk_hash,
+                                            client->data.public_key,
+                                            client);
+
            silc_server_remove_from_channels(server, NULL, client, TRUE,
                                             NULL, TRUE, FALSE);
            silc_idlist_del_data(client);
@@ -2216,10 +2269,9 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   SilcIDListData idata;
   char *username = NULL, *realname = NULL;
   SilcUInt16 username_len;
-  SilcUInt32 id_len;
+  SilcUInt32 id_len, tmp_len;
   int ret;
-  char *hostname, *nickname;
-  int nickfail = 0;
+  char *hostname, *nickname, *nicknamec;
 
   SILC_LOG_DEBUG(("Creating new client"));
 
@@ -2282,17 +2334,30 @@ SilcClientEntry silc_server_new_client(SilcServer server,
     return NULL;
   }
 
-  if (username_len > 128)
+  if (username_len > 128) {
     username[128] = '\0';
+    username_len = 128;
+  }
 
-  /* Check for bad characters for nickname, and modify the nickname if
-     it includes those. */
-  if (silc_server_name_bad_chars(username, username_len)) {
-    nickname = silc_server_name_modify_bad(username, username_len);
-  } else {
-    nickname = strdup(username);
+  /* Check for valid username string */
+  nicknamec = silc_identifier_check(username, username_len,
+                                   SILC_STRING_UTF8, 128, &tmp_len);
+  if (!nicknamec) {
+    silc_free(username);
+    silc_free(realname);
+    SILC_LOG_ERROR(("Client %s (%s) sent bad username string '%s', closing "
+                   "connection", sock->hostname, sock->ip, username));
+    silc_server_disconnect_remote(server, sock,
+                                 SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+                                 NULL);
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    return NULL;
   }
 
+  /* Nickname is initially same as username */
+  nickname = strdup(username);
+
   /* Make sanity checks for the hostname of the client. If the hostname
      is provided in the `username' check that it is the same than the
      resolved hostname, or if not resolved the hostname that appears in
@@ -2381,17 +2446,14 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   }
 
   /* Create Client ID */
-  while (!silc_id_create_client_id(server, server->id, server->rng,
-                                  server->md5hash, nickname, &client_id)) {
-    nickfail++;
-    if (nickfail > 9) {
-      silc_server_disconnect_remote(server, sock,
-                                   SILC_STATUS_ERR_BAD_NICKNAME, NULL);
-      if (sock->user_data)
-       silc_server_free_sock_user_data(server, sock, NULL);
-      return NULL;
-    }
-    snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail);
+  if (!silc_id_create_client_id(server, server->id, server->rng,
+                               server->md5hash, nicknamec,
+                               strlen(nicknamec), &client_id)) {
+    silc_server_disconnect_remote(server, sock,
+                                 SILC_STATUS_ERR_BAD_NICKNAME, NULL);
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    return NULL;
   }
 
   /* If client marked as anonymous, scramble the username and hostname */
@@ -2422,7 +2484,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   id_len = silc_id_get_len(client_id, SILC_ID_CLIENT);
 
   /* Add the client again to the ID cache */
-  silc_idcache_add(server->local_list->clients, client->nickname,
+  silc_idcache_add(server->local_list->clients, nicknamec,
                   client_id, client, 0, NULL);
 
   /* Notify our router about new client on the SILC network */
@@ -2468,7 +2530,7 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   SilcServerEntry new_server, server_entry;
   SilcServerID *server_id;
   SilcIDListData idata;
-  unsigned char *server_name, *id_string;
+  unsigned char *server_name, *server_namec, *id_string;
   SilcUInt16 id_len, name_len;
   int ret;
   bool local = TRUE;
@@ -2483,6 +2545,10 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   new_server = (SilcServerEntry)sock->user_data;
   idata = (SilcIDListData)new_server;
 
+  /* Statistics */
+  if (server->server_type == SILC_ROUTER)
+    server->stat.cell_servers++;
+
   /* Remove the old cache entry */
   if (!silc_idcache_del_by_context(server->local_list->servers, new_server)) {
     if (!silc_idcache_del_by_context(server->global_list->servers,
@@ -2537,8 +2603,10 @@ SilcServerEntry silc_server_new_server(SilcServer server,
     return NULL;
   }
 
-  if (name_len > 256)
-    server_name[255] = '\0';
+  if (name_len > 256) {
+    server_name[256] = '\0';
+    name_len = 256;
+  }
 
   /* Get Server ID */
   server_id = silc_id_str2id(id_string, id_len, SILC_ID_SERVER);
@@ -2571,6 +2639,8 @@ SilcServerEntry silc_server_new_server(SilcServer server,
                                               server_id, TRUE, NULL);
   if (server_entry) {
     if (SILC_IS_LOCAL(server_entry)) {
+      SILC_LOG_ERROR(("Too many registrations from %s (%s)",
+                     sock->ip, sock->hostname));
       silc_server_disconnect_remote(server, sock,
                                    SILC_STATUS_ERR_OPERATION_ALLOWED,
                                    "Too many registrations");
@@ -2585,6 +2655,8 @@ SilcServerEntry silc_server_new_server(SilcServer server,
                                                 server_id, TRUE, NULL);
     if (server_entry) {
       if (SILC_IS_LOCAL(server_entry)) {
+        SILC_LOG_ERROR(("Too many registrations from %s (%s)",
+                       sock->ip, sock->hostname));
        silc_server_disconnect_remote(server, sock,
                                      SILC_STATUS_ERR_OPERATION_ALLOWED,
                                      "Too many registrations");
@@ -2598,6 +2670,20 @@ SilcServerEntry silc_server_new_server(SilcServer server,
     }
   }
 
+  /* Check server name */
+  server_namec = silc_identifier_check(server_name, strlen(server_name),
+                                      SILC_STRING_UTF8, 256, NULL);
+  if (!server_namec) {
+    SILC_LOG_ERROR(("Malformed server name from %s (%s)",
+                   sock->ip, sock->hostname));
+    silc_server_disconnect_remote(server, sock,
+                                 SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                 "Malfromed server name");
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    return NULL;
+  }
+
   /* Update server entry */
   idata->status |= SILC_IDLIST_STATUS_REGISTERED;
   new_server->server_name = server_name;
@@ -2608,7 +2694,7 @@ SilcServerEntry silc_server_new_server(SilcServer server,
 
   /* Add again the entry to the ID cache. */
   silc_idcache_add(local ? server->local_list->servers :
-                  server->global_list->servers, server_name, server_id,
+                  server->global_list->servers, server_namec, server_id,
                   new_server, 0, NULL);
 
   /* Distribute the information about new server in the SILC network
@@ -2626,9 +2712,6 @@ SilcServerEntry silc_server_new_server(SilcServer server,
     silc_server_backup_send(server, sock->user_data, SILC_PACKET_NEW_ID, 0,
                            idp->data, idp->len, FALSE, TRUE);
     silc_buffer_free(idp);
-
-    /* Statistics */
-    server->stat.cell_servers++;
   }
 
   /* Check whether this router connection has been replaced by an
@@ -2806,6 +2889,21 @@ static void silc_server_new_id_real(SilcServer server,
       /* Check if anyone is watching this nickname */
       if (server->server_type == SILC_ROUTER && id_list == server->local_list)
        silc_server_check_watcher_list(server, entry, NULL, 0);
+
+      if (server->server_type == SILC_ROUTER) {
+       /* Add the client's public key to hash table or get the key with
+          GETKEY command. */
+        if (entry->data.public_key) {
+         if (!silc_hash_table_find_by_context(server->pk_hash,
+                                              entry->data.public_key,
+                                              entry, NULL))
+           silc_hash_table_add(server->pk_hash, entry->data.public_key,
+                               entry);
+       } else
+         silc_server_send_command(server, router_sock,
+                                  SILC_COMMAND_GETKEY, ++server->cmd_ident,
+                                  1, 1, buffer->data, buffer->len);
+      }
     }
     break;
 
@@ -2980,7 +3078,7 @@ void silc_server_new_channel(SilcServer server,
 {
   SilcChannelPayload payload;
   SilcChannelID *channel_id;
-  char *channel_name;
+  char *channel_name, *channel_namec = NULL;
   SilcUInt32 name_len;
   unsigned char *id;
   SilcUInt32 id_len, cipher_len;
@@ -3007,8 +3105,16 @@ void silc_server_new_channel(SilcServer server,
   }
 
   channel_name = silc_channel_get_name(payload, &name_len);
-  if (name_len > 256)
-    channel_name[255] = '\0';
+  if (name_len > 256) {
+    channel_name[256] = '\0';
+    name_len = 256;
+  }
+
+  /* Check channel name */
+  channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+                                         SILC_STRING_UTF8, 256, NULL);
+  if (!channel_namec)
+    return;
 
   id = silc_channel_get_id(payload, &id_len);
 
@@ -3020,10 +3126,10 @@ void silc_server_new_channel(SilcServer server,
 
     /* Check that we don't already have this channel */
     channel = silc_idlist_find_channel_by_name(server->local_list,
-                                              channel_name, NULL);
+                                              channel_namec, NULL);
     if (!channel)
       channel = silc_idlist_find_channel_by_name(server->global_list,
-                                                channel_name, NULL);
+                                                channel_namec, NULL);
     if (!channel) {
       SILC_LOG_DEBUG(("New channel id(%s) from [Router] %s",
                      silc_id_render(channel_id, SILC_ID_CHANNEL),
@@ -3054,10 +3160,10 @@ void silc_server_new_channel(SilcServer server,
 
     /* Check that we don't already have this channel */
     channel = silc_idlist_find_channel_by_name(server->local_list,
-                                              channel_name, NULL);
+                                              channel_namec, NULL);
     if (!channel)
       channel = silc_idlist_find_channel_by_name(server->global_list,
-                                                channel_name, NULL);
+                                                channel_namec, NULL);
 
     /* If the channel does not exist, then create it. This creates a new
        key to the channel as well that we will send to the server. */
@@ -3244,6 +3350,7 @@ void silc_server_new_channel(SilcServer server,
                            FALSE, TRUE);
   }
 
+  silc_free(channel_namec);
   silc_channel_payload_free(payload);
 }
 
@@ -3556,9 +3663,9 @@ void silc_server_resume_client(SilcServer server,
   SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry detached_client;
   SilcClientID *client_id = NULL;
-  unsigned char *id_string, *auth = NULL;
+  unsigned char *id_string, *auth = NULL, *nicknamec = NULL;
   SilcUInt16 id_len, auth_len = 0;
-  int ret, nickfail = 0;
+  int ret;
   bool resolved, local, nick_change = FALSE, resolve = FALSE;
   SilcChannelEntry channel;
   SilcHashTableList htl;
@@ -3631,6 +3738,36 @@ void silc_server_resume_client(SilcServer server,
       return;
     }
 
+    if (detached_client->data.status & SILC_IDLIST_STATUS_RESUMED) {
+      SILC_LOG_ERROR(("Client %s (%s) tried to attach more than once, "
+                     "closing connection", sock->hostname, sock->ip));
+      silc_server_disconnect_remote(server, sock,
+                                    SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+                                   "Resuming not possible");
+      if (sock->user_data)
+       silc_server_free_sock_user_data(server, sock, NULL);
+      silc_free(client_id);
+
+      return;
+    }
+
+    if (detached_client->resuming_client &&
+       detached_client->resuming_client != client) {
+      SILC_LOG_ERROR(("Client %s (%s) tried to attach more than once, "
+                     "closing connection", sock->hostname, sock->ip));
+      silc_server_disconnect_remote(server, sock,
+                                    SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+                                   "Resuming not possible");
+      if (sock->user_data)
+       silc_server_free_sock_user_data(server, sock, NULL);
+      silc_free(client_id);
+
+      return;
+    }
+
+    if (!detached_client->resuming_client)
+      detached_client->resuming_client = client;
+
     if (!(detached_client->mode & SILC_UMODE_DETACHED))
       resolve = TRUE;
     if (!silc_hash_table_count(detached_client->channels) &&
@@ -3748,15 +3885,58 @@ void silc_server_resume_client(SilcServer server,
       return;
     }
 
+    /* Check nickname */
+    nicknamec = silc_identifier_check(detached_client->nickname,
+                                     strlen(detached_client->nickname),
+                                     SILC_STRING_UTF8, 128, NULL);
+    if (!nicknamec) {
+      silc_server_disconnect_remote(server, sock,
+                                   SILC_STATUS_ERR_BAD_NICKNAME,
+                                   "Malformed nickname, cannot resume");
+      if (sock->user_data)
+       silc_server_free_sock_user_data(server, sock, NULL);
+      return;
+    }
+
+    /* If the ID is not based in our ID then change it */
+    if (!SILC_ID_COMPARE(detached_client->id, server->id,
+                        server->id->ip.data_len)) {
+      silc_free(client_id);
+      if (!silc_id_create_client_id(server, server->id, server->rng,
+                                   server->md5hash, nicknamec,
+                                   strlen(nicknamec), &client_id)) {
+       silc_server_disconnect_remote(server, sock,
+                                     SILC_STATUS_ERR_BAD_NICKNAME,
+                                     "Resuming not possible");
+       if (sock->user_data)
+         silc_server_free_sock_user_data(server, sock, NULL);
+       return;
+      }
+      nick_change = TRUE;
+    }
+
     /* Now resume the client to the network */
 
     silc_schedule_task_del_by_context(server->schedule, detached_client);
     sock->user_data = detached_client;
     detached_client->connection = sock;
 
+    if (detached_client->data.public_key)
+      silc_hash_table_del_by_context(server->pk_hash,
+                                    detached_client->data.public_key,
+                                    detached_client);
+    if (idata->public_key)
+      silc_hash_table_del_by_context(server->pk_hash,
+                                    idata->public_key, idata);
+
     /* Take new keys and stuff into use in the old entry */
     silc_idlist_del_data(detached_client);
     silc_idlist_add_data(detached_client, idata);
+
+    if (detached_client->data.public_key)
+      silc_hash_table_add(server->pk_hash,
+                         detached_client->data.public_key, detached_client);
+
     detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
     detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
     detached_client->data.status |= SILC_IDLIST_STATUS_LOCAL;
@@ -3764,6 +3944,28 @@ void silc_server_resume_client(SilcServer server,
     detached_client->mode &= ~SILC_UMODE_DETACHED;
     server->stat.my_detached--;
 
+    /* We are finished - reset resuming client */
+    detached_client->resuming_client = NULL;
+
+    /* Check if anyone is watching this client */
+    if (server->server_type == SILC_ROUTER)
+      silc_server_check_watcher_list(server, detached_client, NULL,
+                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
+
+    /* Delete this current client entry since we're resuming to old one. */
+    server->stat.my_clients--;
+    server->stat.clients--;
+    if (server->stat.cell_clients)
+      server->stat.cell_clients--;
+    silc_server_remove_from_channels(server, NULL, client, FALSE,
+                                    NULL, FALSE, FALSE);
+    silc_server_del_from_watcher_list(server, client);
+    if (!silc_idlist_del_client(server->local_list, client))
+      silc_idlist_del_client(server->global_list, client);
+    client = detached_client;
+    silc_free(client->servername);
+    client->servername = strdup(server->server_name);
+
     /* Send the RESUME_CLIENT packet to our primary router so that others
        know this client isn't detached anymore. */
     buf = silc_buffer_alloc_size(2 + id_len);
@@ -3776,54 +3978,19 @@ void silc_server_resume_client(SilcServer server,
     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_RESUME_CLIENT, 0,
                            buf->data, buf->len, TRUE);
-    silc_server_backup_send(server, detached_client->router,
+    silc_server_backup_send(server, client->router,
                            SILC_PACKET_RESUME_CLIENT, 0,
                            buf->data, buf->len, TRUE, TRUE);
 
     /* As router we must deliver this packet directly to the original
        server whom this client was earlier. */
-    if (server->server_type == SILC_ROUTER && detached_client->router &&
-       detached_client->router->server_type != SILC_ROUTER)
-      silc_server_packet_send(server, detached_client->router->connection,
+    if (server->server_type == SILC_ROUTER && client->router &&
+       client->router->server_type != SILC_ROUTER)
+      silc_server_packet_send(server, client->router->connection,
                              SILC_PACKET_RESUME_CLIENT, 0,
                              buf->data, buf->len, TRUE);
     silc_buffer_free(buf);
-
-    detached_client->router = NULL;
-
-    /* Delete this client entry since we're resuming to old one. */
-    server->stat.my_clients--;
-    server->stat.clients--;
-    if (server->stat.cell_clients)
-      server->stat.cell_clients--;
-    silc_server_remove_from_channels(server, NULL, client, FALSE,
-                                    NULL, FALSE, FALSE);
-    silc_server_del_from_watcher_list(server, client);
-    if (!silc_idlist_del_client(server->local_list, client))
-      silc_idlist_del_client(server->global_list, client);
-    client = detached_client;
-    silc_free(client->servername);
-    client->servername = strdup(server->server_name);
-
-    /* If the ID is not based in our ID then change it */
-    if (!SILC_ID_COMPARE(client->id, server->id, server->id->ip.data_len)) {
-      silc_free(client_id);
-      while (!silc_id_create_client_id(server, server->id, server->rng,
-                                      server->md5hash, client->nickname,
-                                      &client_id)) {
-       nickfail++;
-       if (nickfail > 9) {
-         silc_server_disconnect_remote(server, sock,
-                                       SILC_STATUS_ERR_BAD_NICKNAME, NULL);
-         if (sock->user_data)
-           silc_server_free_sock_user_data(server, sock, NULL);
-         return;
-       }
-       snprintf(&client->nickname[strlen(client->nickname) - 1], 1,
-                "%d", nickfail);
-      }
-      nick_change = TRUE;
-    }
+    client->router = NULL;
 
     if (nick_change) {
       /* Notify about Client ID change, nickname doesn't actually change. */
@@ -3837,7 +4004,7 @@ void silc_server_resume_client(SilcServer server,
        haven't resolved user list yet. */
     if (server->server_type == SILC_SERVER && !server->standalone) {
       silc_hash_table_list(client->channels, &htl);
-      while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+      while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
        channel = chl->channel;
        SILC_LOG_DEBUG(("Resolving users for %s channel",
                        channel->channel_name));
@@ -3877,7 +4044,7 @@ void silc_server_resume_client(SilcServer server,
     silc_free(client->id);
     client->id = client_id;
     client_id = NULL;
-    silc_idcache_add(server->local_list->clients, client->nickname,
+    silc_idcache_add(server->local_list->clients, nicknamec,
                     client->id, client, 0, NULL);
 
     /* Send some nice info to the client */
@@ -3885,7 +4052,7 @@ void silc_server_resume_client(SilcServer server,
 
     /* Send all channel keys of channels the client has joined */
     silc_hash_table_list(client->channels, &htl);
-    while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+    while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
       bool created = FALSE;
       channel = chl->channel;
 
@@ -3974,6 +4141,17 @@ void silc_server_resume_client(SilcServer server,
       return;
     }
 
+    /* Check nickname */
+    if (detached_client->nickname) {
+      nicknamec = silc_identifier_check(detached_client->nickname,
+                                       strlen(detached_client->nickname),
+                                       SILC_STRING_UTF8, 128, NULL);
+      if (!nicknamec) {
+       silc_free(client_id);
+       return;
+      }
+    }
+
     SILC_LOG_DEBUG(("Resuming detached client"));
 
     /* If the sender of this packet is server and we are router we need to
@@ -3994,12 +4172,23 @@ void silc_server_resume_client(SilcServer server,
 
     /* Client is detached, and now it is resumed.  Remove the detached
        mode and mark that it is resumed. */
+
+    if (detached_client->data.public_key)
+      silc_hash_table_del_by_context(server->pk_hash,
+                                    detached_client->data.public_key,
+                                    detached_client);
+
     silc_idlist_del_data(detached_client);
     detached_client->mode &= ~SILC_UMODE_DETACHED;
     detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
     detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
     id_cache->expire = 0;
 
+    /* Check if anyone is watching this client */
+    if (server->server_type == SILC_ROUTER)
+      silc_server_check_watcher_list(server, detached_client, NULL,
+                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
+
     silc_schedule_task_del_by_context(server->schedule, detached_client);
 
     /* Get the new owner of the resumed client */
@@ -4037,8 +4226,7 @@ void silc_server_resume_client(SilcServer server,
                                  detached_client);
     silc_idcache_add(local && server->server_type == SILC_ROUTER ?
                     server->local_list->clients :
-                    server->global_list->clients,
-                    detached_client->nickname,
+                    server->global_list->clients, nicknamec,
                     detached_client->id, detached_client, FALSE, NULL);
 
     /* Change the owner of the client */
@@ -4047,7 +4235,7 @@ void silc_server_resume_client(SilcServer server,
     /* Update channel information regarding global clients on channel. */
     if (server->server_type != SILC_ROUTER) {
       silc_hash_table_list(detached_client->channels, &htl);
-      while (silc_hash_table_get(&htl, NULL, (void **)&chl))
+      while (silc_hash_table_get(&htl, NULL, (void *)&chl))
        chl->channel->global_users =
          silc_server_channel_has_global(chl->channel);
       silc_hash_table_list_reset(&htl);
index b72ac0f3012379add36543e2f4e3b8ad19baafb8..a7b13f0d099a64de8e61a853f513ae63049d1f7e 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -35,13 +35,17 @@ int silc_server_packet_send_real(SilcServer server,
   int ret;
 
   /* If disconnecting, ignore the data */
-  if (SILC_IS_DISCONNECTING(sock))
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
     return -1;
 
   /* Send the packet */
   ret = silc_packet_send(sock, FALSE);
   if (ret != -2) {
     if (ret == -1) {
+      SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
+      SILC_UNSET_OUTBUF_PENDING(sock);
+      silc_buffer_clear(sock->outbuf);
+
       SILC_LOG_ERROR(("Error sending packet to connection "
                      "%s:%d [%s]", sock->hostname, sock->port,
                      (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
@@ -49,8 +53,17 @@ int silc_server_packet_send_real(SilcServer server,
                       sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
                       "Router")));
 
-      if (sock->user_data)
+      if (sock->user_data) {
+       /* If backup then mark that resuming will not be allowed */
+       if (server->server_type == SILC_ROUTER && !server->backup_router &&
+           sock->type == SILC_SOCKET_TYPE_SERVER) {
+         SilcServerEntry server_entry = sock->user_data;
+         if (server_entry->server_type == SILC_BACKUP_ROUTER)
+           server->backup_closed = TRUE;
+       }
+
        silc_server_free_sock_user_data(server, sock, NULL);
+      }
       SILC_SET_DISCONNECTING(sock);
       silc_server_close_connection(server, sock);
       return ret;
@@ -98,14 +111,15 @@ void silc_server_packet_send(SilcServer server,
   idata = (SilcIDListData)sock->user_data;
 
   /* If disconnecting, ignore the data */
-  if (SILC_IS_DISCONNECTING(sock))
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
     return;
 
   /* If entry is disabled do not sent anything.  Allow hearbeat and
      rekeys, though */
   if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
        type != SILC_PACKET_HEARTBEAT && type != SILC_PACKET_REKEY &&
-       type != SILC_PACKET_REKEY_DONE) ||
+       type != SILC_PACKET_REKEY_DONE && type != SILC_PACKET_KEY_EXCHANGE_1
+       && type != SILC_PACKET_KEY_EXCHANGE_2) ||
       (sock->user_data == server->id_entry)) {
     SILC_LOG_DEBUG(("Connection is disabled"));
     return;
@@ -162,14 +176,18 @@ void silc_server_packet_send_dest(SilcServer server,
   int block_len = 0;
 
   /* If disconnecting, ignore the data */
-  if (!sock || SILC_IS_DISCONNECTING(sock))
+  if (!sock || SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock))
     return;
 
   idata = (SilcIDListData)sock->user_data;
 
-  /* If entry is disabled do not sent anything. */
-  if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
-      sock->user_data == server->id_entry) {
+  /* If entry is disabled do not sent anything.  Allow hearbeat and
+     rekeys, though */
+  if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
+       type != SILC_PACKET_HEARTBEAT && type != SILC_PACKET_REKEY &&
+       type != SILC_PACKET_REKEY_DONE && type != SILC_PACKET_KEY_EXCHANGE_1
+       && type != SILC_PACKET_KEY_EXCHANGE_2) ||
+      (sock->user_data == server->id_entry)) {
     SILC_LOG_DEBUG(("Connection is disabled"));
     return;
   }
@@ -276,9 +294,13 @@ void silc_server_packet_send_srcdest(SilcServer server,
   /* Get data used in the packet sending, keys and stuff */
   idata = (SilcIDListData)sock->user_data;
 
-  /* If entry is disabled do not sent anything. */
-  if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
-      sock->user_data == server->id_entry) {
+  /* If entry is disabled do not sent anything.  Allow hearbeat and
+     rekeys, though */
+  if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
+       type != SILC_PACKET_HEARTBEAT && type != SILC_PACKET_REKEY &&
+       type != SILC_PACKET_REKEY_DONE && type != SILC_PACKET_KEY_EXCHANGE_1
+       && type != SILC_PACKET_KEY_EXCHANGE_2) ||
+      (sock->user_data == server->id_entry)) {
     SILC_LOG_DEBUG(("Connection is disabled"));
     return;
   }
@@ -467,7 +489,7 @@ void silc_server_packet_send_clients(SilcServer server,
 
   /* Send to all clients in table */
   silc_hash_table_list(clients, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&client)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&client)) {
     /* If client has router set it is not locally connected client and
        we will route the message to the router set in the client. Though,
        send locally connected server in all cases. */
@@ -655,7 +677,7 @@ void silc_server_packet_send_to_channel(SilcServer server,
 
   /* Send the message to clients on the channel's client list. */
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     client = chl->client;
     if (!client)
       continue;
@@ -750,6 +772,7 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
 {
   SilcUInt32 mac_len, iv_len;
   unsigned char iv[SILC_CIPHER_MAX_IV_SIZE];
+  SilcUInt16 totlen, len;
 
   /* If we are router and the packet came from router and private key
      has not been set for the channel then we must encrypt the packet
@@ -775,9 +798,23 @@ silc_server_packet_relay_to_channel_encrypt(SilcServer server,
       return FALSE;
     }
 
+    totlen = 2;
+    SILC_GET16_MSB(len, data + totlen);
+    totlen += 2 + len;
+    if (totlen + iv_len + mac_len + 2 > data_len) {
+      SILC_LOG_WARNING(("Corrupted channel message, cannot relay it"));
+      return FALSE;
+    }
+    SILC_GET16_MSB(len, data + totlen);
+    totlen += 2 + len;
+    if (totlen + iv_len + mac_len > data_len) {
+      SILC_LOG_WARNING(("Corrupted channel message, cannot relay it"));
+      return FALSE;
+    }
+
     memcpy(iv, data + (data_len - iv_len - mac_len), iv_len);
-    silc_message_payload_encrypt(data, data_len - iv_len, data_len,
-                                iv, iv_len, channel->channel_key,
+    silc_message_payload_encrypt(data, totlen, data_len - mac_len,
+                                 iv, iv_len, channel->channel_key,
                                 channel->hmac);
   }
 
@@ -871,7 +908,7 @@ void silc_server_packet_relay_to_channel(SilcServer server,
 
   /* Send the message to clients on the channel's client list. */
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     client = chl->client;
     if (!client || client == sender_entry)
       continue;
@@ -1039,7 +1076,7 @@ void silc_server_packet_send_local_channel(SilcServer server,
 
   /* Send the message to clients on the channel's client list. */
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     if (chl->client && SILC_IS_LOCAL(chl->client)) {
       sock = chl->client->connection;
 
@@ -1290,16 +1327,18 @@ void silc_server_send_notify_cmode(SilcServer server,
                                   SilcBuffer channel_pubkeys)
 {
   SilcBuffer idp, fkey = NULL;
-  unsigned char mode[4];
+  unsigned char mode[4], ulimit[4];
 
   idp = silc_id_payload_encode((void *)id, id_type);
   SILC_PUT32_MSB(mode_mask, mode);
   if (founder_key)
     fkey = silc_pkcs_public_key_payload_encode(founder_key);
+  if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
+    SILC_PUT32_MSB(channel->user_limit, ulimit);
 
   silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
                               SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
-                              7, idp->data, idp->len,
+                              8, idp->data, idp->len,
                               mode, 4,
                               cipher, cipher ? strlen(cipher) : 0,
                               hmac, hmac ? strlen(hmac) : 0,
@@ -1307,7 +1346,11 @@ void silc_server_send_notify_cmode(SilcServer server,
                               strlen(passphrase) : 0,
                               fkey ? fkey->data : NULL, fkey ? fkey->len : 0,
                               channel_pubkeys ? channel_pubkeys->data : NULL,
-                              channel_pubkeys ? channel_pubkeys->len : 0);
+                              channel_pubkeys ? channel_pubkeys->len : 0,
+                              mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
+                              ulimit : NULL,
+                              mode_mask & SILC_CHANNEL_MODE_ULIMIT ?
+                              sizeof(ulimit) : 0);
   silc_buffer_free(fkey);
   silc_buffer_free(idp);
 }
@@ -1524,22 +1567,28 @@ void silc_server_send_notify_watch(SilcServer server,
                                   SilcClientEntry watcher,
                                   SilcClientEntry client,
                                   const char *nickname,
-                                  SilcNotifyType type)
+                                  SilcNotifyType type,
+                                  SilcPublicKey public_key)
 {
-  SilcBuffer idp;
+  SilcBuffer idp, pkp = NULL;
   unsigned char mode[4], n[2];
 
   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
   SILC_PUT16_MSB(type, n);
   SILC_PUT32_MSB(client->mode, mode);
+  if (public_key)
+    pkp = silc_pkcs_public_key_payload_encode(public_key);
   silc_server_send_notify_dest(server, sock, FALSE, watcher->id,
                               SILC_ID_CLIENT, SILC_NOTIFY_TYPE_WATCH,
-                              4, idp->data, idp->len,
+                              5, idp->data, idp->len,
                               nickname, nickname ? strlen(nickname) : 0,
                               mode, sizeof(mode),
                               type != SILC_NOTIFY_TYPE_NONE ?
-                              n : NULL, sizeof(n));
+                              n : NULL, sizeof(n),
+                              pkp ? pkp->data : NULL,
+                              pkp ? pkp->len : 0);
   silc_buffer_free(idp);
+  silc_buffer_free(pkp);
 }
 
 /* Sends notify message destined to specific entity. */
@@ -1656,12 +1705,12 @@ void silc_server_send_notify_on_channels(SilcServer server,
   packetdata.src_id_type = SILC_ID_SERVER;
 
   silc_hash_table_list(client->channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     channel = chl->channel;
 
     /* Send the message to all clients on the channel's client list. */
     silc_hash_table_list(channel->user_list, &htl2);
-    while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
+    while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
       c = chl2->client;
 
       if (sender && c == sender)
@@ -2003,19 +2052,35 @@ void silc_server_send_connection_auth_request(SilcServer server,
 }
 
 /* Purge the outgoing packet queue to the network if there is data. This
-   function can be used to empty the packet queue. It is guaranteed that
-   after this function returns the outgoing data queue is empty. */
+   function can be used to empty the packet queue. */
 
 void silc_server_packet_queue_purge(SilcServer server,
                                    SilcSocketConnection sock)
 {
   if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
       !(SILC_IS_DISCONNECTING(sock)) && !(SILC_IS_DISCONNECTED(sock))) {
+    int ret;
+
     SILC_LOG_DEBUG(("Purging outgoing queue"));
+
     server->stat.packets_sent++;
-    silc_packet_send(sock, TRUE);
-    SILC_UNSET_OUTBUF_PENDING(sock);
+    ret = silc_packet_send(sock, TRUE);
+    if (ret == -2) {
+      if (sock->outbuf && sock->outbuf->len > 0) {
+       /* Couldn't send all data, put the queue back up, we'll send
+          rest later. */
+       SILC_LOG_DEBUG(("Could not purge immediately, sending rest later"));
+       SILC_SET_CONNECTION_FOR_OUTPUT(server->schedule, sock->sock);
+       SILC_SET_OUTBUF_PENDING(sock);
+       return;
+      }
+    } else if (ret == -1) {
+      SILC_LOG_ERROR(("Error purging packet queue, packets dropped"));
+    }
+
+    /* Purged all data */
     SILC_SET_CONNECTION_FOR_INPUT(server->schedule, sock->sock);
+    SILC_UNSET_OUTBUF_PENDING(sock);
     silc_buffer_clear(sock->outbuf);
   }
 }
index 6c85c3a8c6c8a52d7bba8deced511e7a201bfd01..2b0681b6012079463602f9fa9fbecc270878b880 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -200,7 +199,8 @@ void silc_server_send_notify_watch(SilcServer server,
                                   SilcClientEntry watcher,
                                   SilcClientEntry client,
                                   const char *nickname,
-                                  SilcNotifyType type);
+                                  SilcNotifyType type,
+                                  SilcPublicKey public_key);
 void silc_server_send_notify_dest(SilcServer server,
                                  SilcSocketConnection sock,
                                  bool broadcast,
@@ -285,4 +285,4 @@ void silc_server_send_opers_notify(SilcServer server,
                                   SilcNotifyType type,
                                   SilcUInt32 argc, ...);
 
-#endif
+#endif /* PACKET_SEND_H */
index f232c3d84f94cb86384443fe1b7f766a502451d9..06e80fd4e696f2521c2d83ef100ecb8ed2f54f8e 100644 (file)
@@ -1400,6 +1400,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
           */
 
          /* Send the REKEY_DONE to indicate we will take new keys into use */
+         silc_server_packet_queue_purge(server, ctx->sock);
          silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                                  0, NULL, 0, FALSE);
 
@@ -1456,6 +1457,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
 
          /* Send the REKEY_DONE to indicate we will take new keys into use
             now. */
+         silc_server_packet_queue_purge(server, ctx->sock);
          silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                                  0, NULL, 0, FALSE);
 
@@ -1524,6 +1526,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
 
     /* Send the REKEY_DONE to indicate we will take new keys into use
        now. */
+    silc_server_packet_queue_purge(server, ctx->sock);
     silc_server_packet_send(server, ctx->sock, SILC_PACKET_REKEY_DONE,
                            0, NULL, 0, FALSE);
 
@@ -1531,6 +1534,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
        key to the new key since all packets after this packet must
        encrypted with the new key. */
     silc_server_protocol_rekey_generate_pfs(server, ctx, TRUE);
+    silc_server_packet_queue_purge(server, ctx->sock);
 
     /* The protocol ends in next stage. */
     protocol->state = SILC_PROTOCOL_STATE_END;
@@ -1558,6 +1562,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_rekey)
       silc_server_protocol_rekey_generate_pfs(server, ctx, FALSE);
     else
       silc_server_protocol_rekey_generate(server, ctx, FALSE);
+    silc_server_packet_queue_purge(server, ctx->sock);
 
     /* Assure that after calling final callback there cannot be pending
        executions for this protocol anymore. This just unregisters any
index 6c1e03d1c7971bcbcdd6f24d1a59354bfca73ebe..5488bb315659a5417fbaf692ecbf5ae8b065e807 100644 (file)
@@ -97,11 +97,11 @@ SilcSocketConnection silc_server_route_get(SilcServer server, void *id,
 #endif
 
     router = silc_server_route_check(dest, port);
-    if (!router)
-      return (SilcSocketConnection)server->id_entry->router->connection;
-
-    return (SilcSocketConnection)router->connection;
+    if (router)
+        return (SilcSocketConnection)router->connection;
   }
 
-  return (SilcSocketConnection)server->id_entry->router->connection;
+  return (server->id_entry->router) 
+       ? (SilcSocketConnection)server->id_entry->router->connection
+       : NULL;
 }
index adc45d2c9842879d7625206478c1b25d75708161..0e78e739a4b66f91f57aaaa16a4a3bea2cdf462b 100644 (file)
@@ -54,7 +54,7 @@ extern SilcServerRouteTable silc_route_cache[SILC_SERVER_ROUTE_SIZE];
 /* Returns route cache hash table entry index. This is IPv4 specific.
    `port' argument may be zero (0) if it doesn't exist.  This has been
    taken from Linux kernel's route cache code. */
-extern inline
+static inline
 SilcUInt32 silc_server_route_hash(unsigned int addr, 
                                    SilcUInt16 port)
 {
index 963746f9045acc439a214a8294b17724b529f0cd..2c3875a5c12bc8826866dcbfbe418621fddc5a20 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -42,6 +42,7 @@ SILC_TASK_CALLBACK(silc_server_free_client_data_timeout);
 SILC_TASK_CALLBACK(silc_server_timeout_remote);
 SILC_TASK_CALLBACK(silc_server_channel_key_rekey);
 SILC_TASK_CALLBACK(silc_server_get_stats);
+SILC_TASK_CALLBACK(silc_server_connect_router);
 
 /* Allocates a new SILC server object. This has to be done before the server
    can be used. After allocation one must call silc_server_init to initialize
@@ -128,6 +129,9 @@ void silc_server_free(SilcServer server)
   if (list)
     silc_idcache_list_free(list);
 
+  if (server->pk_hash)
+    silc_hash_table_free(server->pk_hash);
+
   /* Delete all clients */
   list = NULL;
   if (silc_idcache_get_all(server->local_list->clients, &list) &&
@@ -148,6 +152,7 @@ void silc_server_free(SilcServer server)
   if (list)
     silc_idcache_list_free(list);
 
+
   /* Delete all servers */
   list = NULL;
   if (silc_idcache_get_all(server->local_list->servers, &list) &&
@@ -175,6 +180,7 @@ void silc_server_free(SilcServer server)
   silc_idcache_free(server->global_list->servers);
   silc_idcache_free(server->global_list->channels);
   silc_hash_table_free(server->watcher_list);
+  silc_hash_table_free(server->watcher_list_pk);
 
   silc_hash_free(server->md5hash);
   silc_hash_free(server->sha1hash);
@@ -336,25 +342,46 @@ bool silc_server_init(SilcServer server)
 
   /* Initialize ID caches */
   server->local_list->clients =
-    silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor);
-  server->local_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
-  server->local_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
+    silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
+                      FALSE, TRUE);
+  server->local_list->servers =
+    silc_idcache_alloc(0, SILC_ID_SERVER, NULL, FALSE, TRUE);
+  server->local_list->channels =
+    silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, FALSE, TRUE);
 
   /* These are allocated for normal server as well as these hold some
      global information that the server has fetched from its router. For
      router these are used as they are supposed to be used on router. */
   server->global_list->clients =
-    silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor);
-  server->global_list->servers = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
-  server->global_list->channels = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
-
-  /* Init watcher list */
+    silc_idcache_alloc(0, SILC_ID_CLIENT, silc_idlist_client_destructor,
+                      FALSE, TRUE);
+  server->global_list->servers =
+    silc_idcache_alloc(0, SILC_ID_SERVER, NULL, FALSE, TRUE);
+  server->global_list->channels =
+    silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL, FALSE, TRUE);
+
+  /* Init watcher lists */
   server->watcher_list =
     silc_hash_table_alloc(1, silc_hash_client_id_hash, NULL,
                          silc_hash_data_compare, (void *)CLIENTID_HASH_LEN,
                          NULL, NULL, TRUE);
   if (!server->watcher_list)
     goto err;
+  server->watcher_list_pk =
+    silc_hash_table_alloc(1, silc_hash_public_key, NULL,
+                         silc_hash_public_key_compare, NULL,
+                         NULL, NULL, TRUE);
+  if (!server->watcher_list_pk)
+    goto err;
+
+  /* Init public key list */
+  server->pk_hash =
+    silc_hash_table_alloc(0, silc_hash_public_key, NULL,
+                          silc_hash_public_key_compare, NULL,
+                          NULL, NULL, TRUE);
+
+  if (!server->pk_hash)
+    goto err;
 
   /* Create a listening server */
   if (!silc_server_listen(server,
@@ -564,8 +591,17 @@ bool silc_server_rehash(SilcServer server)
   /* Fix the server_name field */
   if (strcmp(server->server_name, newconfig->server_info->server_name)) {
     silc_free(server->server_name);
-    server->server_name = newconfig->server_info->server_name;
-    newconfig->server_info->server_name = NULL;
+
+    /* Check server name */
+    server->server_name =
+      silc_identifier_check(newconfig->server_info->server_name,
+                           strlen(newconfig->server_info->server_name),
+                           SILC_STRING_LOCALE, 256, NULL);
+    if (!server->server_name) {
+      SILC_LOG_ERROR(("Malformed server name string '%s'",
+                     server->config->server_info->server_name));
+      return FALSE;
+    }
 
     /* Update the idcache list with a fresh pointer */
     silc_free(server->id_entry->server_name);
@@ -574,7 +610,7 @@ bool silc_server_rehash(SilcServer server)
                                     server->id_entry))
       return FALSE;
     if (!silc_idcache_add(server->local_list->servers,
-                         server->id_entry->server_name,
+                         strdup(server->id_entry->server_name),
                          server->id_entry->id, server->id_entry, 0, NULL))
       return FALSE;
   }
@@ -730,8 +766,6 @@ bool silc_server_rehash(SilcServer server)
   if (server->config->debug_string) {
     silc_debug = TRUE;
     silc_log_set_debug_string(server->config->debug_string);
-  } else {
-    silc_debug = FALSE;
   }
 #endif /* SILC_DEBUG */
 
@@ -793,6 +827,7 @@ void silc_server_stop(SilcServer server)
       } else {
        silc_socket_free(server->sockets[i]);
        server->sockets[i] = NULL;
+        server->stat.conn_num--;
       }
     }
 
@@ -924,7 +959,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
   }
   sconn->retry_count++;
   sconn->retry_timeout = sconn->retry_timeout +
-    silc_rng_get_rn32(server->rng) % SILC_SERVER_RETRY_RANDOMIZER;
+    (silc_rng_get_rn32(server->rng) % SILC_SERVER_RETRY_RANDOMIZER);
 
   /* If we've reached max retry count, give up. */
   if ((sconn->retry_count > param->reconnect_count) &&
@@ -949,6 +984,45 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
 
+/* Callback for async connection to remote router */
+
+SILC_TASK_CALLBACK(silc_server_connection_established)
+{
+  SilcServer server = app_context;
+  SilcServerConnection sconn = (SilcServerConnection)context;
+  int sock = fd;
+  int opt = EINVAL, optlen = sizeof(opt), ret;
+
+  ret = silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen);
+
+  silc_schedule_task_del_by_fd(server->schedule, sock);
+  silc_schedule_unset_listen_fd(server->schedule, sock);
+
+  if (ret != 0 || opt != 0) {
+    SILC_LOG_ERROR(("Could not connect to router %s:%d: %s",
+                   sconn->remote_host, sconn->remote_port, strerror(opt)));
+    silc_net_close_connection(sock);
+    if (!sconn->no_reconnect) {
+      silc_schedule_task_add(server->schedule, 0,
+                            silc_server_connect_to_router_retry,
+                            context, 1, 0, SILC_TASK_TIMEOUT,
+                            SILC_TASK_PRI_NORMAL);
+    } else {
+      silc_server_config_unref(&sconn->conn);
+      silc_free(sconn->remote_host);
+      silc_free(sconn->backup_replace_ip);
+      silc_free(sconn);
+    }
+    return;
+  }
+
+  SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
+                sconn->remote_port));
+
+  /* Continue with key exchange protocol */
+  silc_server_start_key_exchange(server, sconn, sock);
+}
+
 /* Generic routine to use connect to a router. */
 
 SILC_TASK_CALLBACK(silc_server_connect_router)
@@ -985,19 +1059,19 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
   silc_server_config_ref(&sconn->conn, server->config, (void *)rconn);
 
   /* Connect to remote host */
-  sock = silc_net_create_connection(
+  sock = silc_net_create_connection_async(
                 (!server->config->server_info->primary ? NULL :
                  server->config->server_info->primary->server_ip),
                 sconn->remote_port, sconn->remote_host);
   if (sock < 0) {
     SILC_LOG_ERROR(("Could not connect to router %s:%d",
                    sconn->remote_host, sconn->remote_port));
-    if (!sconn->no_reconnect)
+    if (!sconn->no_reconnect) {
       silc_schedule_task_add(server->schedule, 0,
                             silc_server_connect_to_router_retry,
-                            context, 0, 1, SILC_TASK_TIMEOUT,
+                            context, 1, 0, SILC_TASK_TIMEOUT,
                             SILC_TASK_PRI_NORMAL);
-    else {
+    else {
       silc_server_config_unref(&sconn->conn);
       silc_free(sconn->remote_host);
       silc_free(sconn->backup_replace_ip);
@@ -1006,8 +1080,13 @@ SILC_TASK_CALLBACK(silc_server_connect_router)
     return;
   }
 
-  /* Continue with key exchange protocol */
-  silc_server_start_key_exchange(server, sconn, sock);
+  /* wait for the connection to be established */
+  silc_schedule_task_add(server->schedule, sock,
+                        silc_server_connection_established,
+                        context, 0, 0, SILC_TASK_FD,
+                        SILC_TASK_PRI_NORMAL);
+  silc_schedule_set_listen_fd(server->schedule, sock,
+                             SILC_TASK_WRITE, FALSE);
 }
 
 /* This function connects to our primary router or if we are a router this
@@ -1159,7 +1238,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     if (!sconn->no_reconnect) {
       silc_schedule_task_add(server->schedule, 0,
                             silc_server_connect_to_router_retry,
-                            sconn, 0, 1, SILC_TASK_TIMEOUT,
+                            sconn, 1, 0, SILC_TASK_TIMEOUT,
                             SILC_TASK_PRI_NORMAL);
       return;
     }
@@ -1202,7 +1281,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_second)
     if (!sconn->no_reconnect) {
       silc_schedule_task_add(server->schedule, 0,
                             silc_server_connect_to_router_retry,
-                            sconn, 0, 1, SILC_TASK_TIMEOUT,
+                            sconn, 1, 0, SILC_TASK_TIMEOUT,
                             SILC_TASK_PRI_NORMAL);
       return;
     }
@@ -1337,7 +1416,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_final)
     if (!sconn->no_reconnect) {
       silc_schedule_task_add(server->schedule, 0,
                             silc_server_connect_to_router_retry,
-                            sconn, 0, 1, SILC_TASK_TIMEOUT,
+                            sconn, 1, 0, SILC_TASK_TIMEOUT,
                             SILC_TASK_PRI_NORMAL);
       goto out2;
     }
@@ -1551,7 +1630,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
                 sock->ip));
 
   /* Listenning port */
-  if (!server->sockets[(SilcUInt32)proto_ctx->context]) {
+  if (!server->sockets[SILC_PTR_TO_32(proto_ctx->context)]) {
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_RESOURCE_LIMIT,
                                  "Connection refused");
@@ -1559,7 +1638,7 @@ silc_server_accept_new_connection_lookup(SilcSocketConnection sock,
     silc_free(proto_ctx);
     return;
   }
-  port = server->sockets[(SilcUInt32)proto_ctx->context]->port;
+  port = server->sockets[SILC_PTR_TO_32(proto_ctx->context)]->port;
 
   /* Check whether this connection is denied to connect to us. */
   deny = silc_server_config_find_denied(server, sock->ip);
@@ -1670,6 +1749,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
     silc_net_close_connection(sock);
     return;
   }
+  server->stat.conn_num++;
 
   /* Set socket options */
   silc_net_set_socket_nonblock(sock);
@@ -1685,7 +1765,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection)
      is accepted further. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   proto_ctx->server = server;
-  proto_ctx->context = (void *)fd;
+  proto_ctx->context = SILC_32_TO_PTR(fd);
   silc_socket_host_lookup(newsocket, TRUE,
                          silc_server_accept_new_connection_lookup,
                          (void *)proto_ctx, server->schedule);
@@ -1905,10 +1985,10 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
          silc_free(sock->user_data);
          server->stat.auth_failures++;
 
-         /* From here on, wait 10 seconds for the backup router to appear. */
+         /* From here on, wait 20 seconds for the backup router to appear. */
          silc_schedule_task_add(server->schedule, 0,
                                 silc_server_backup_router_wait,
-                                (void *)server, 10, 0,
+                                (void *)server, 20, 0,
                                 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
          goto out;
        }
@@ -1959,6 +2039,13 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
          client->mode |= SILC_UMODE_ANONYMOUS;
       }
 
+      /* Add public key to hash list (for whois using attributes) */
+      if (!silc_hash_table_find_by_context(server->pk_hash,
+                                          entry->data.public_key,
+                                          client, NULL))
+       silc_hash_table_add(server->pk_hash,
+                           entry->data.public_key, client);
+
       id_entry = (void *)client;
       break;
     }
@@ -2079,10 +2166,10 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
          silc_free(sock->user_data);
          server->stat.auth_failures++;
 
-         /* From here on, wait 10 seconds for the backup router to appear. */
+         /* From here on, wait 20 seconds for the backup router to appear. */
          silc_schedule_task_add(server->schedule, 0,
                                 silc_server_backup_router_wait,
-                                (void *)server, 10, 0,
+                                (void *)server, 20, 0,
                                 SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
          goto out;
        }
@@ -2142,18 +2229,18 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final)
        /* Remove the backup waiting with timeout */
        silc_schedule_task_add(server->schedule, 0,
                               silc_server_backup_router_wait,
-                              (void *)server, 5, 0,
+                              (void *)server, 10, 0,
                               SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
       }
 
       /* Statistics */
       if (ctx->conn_type == SILC_SOCKET_TYPE_SERVER) {
        server->stat.my_servers++;
+       server->stat.servers++;
       } else {
        server->stat.my_routers++;
        server->stat.routers++;
       }
-      server->stat.servers++;
 
       /* Check whether this connection is to be our primary router connection
         if we do not already have the primary route. */
@@ -2241,6 +2328,9 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     /* Do not send data to disconnected connection */
     if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
       SILC_LOG_DEBUG(("Disconnected socket connection, cannot send"));
+      SILC_SET_CONNECTION_FOR_INPUT(server->schedule, fd);
+      SILC_UNSET_OUTBUF_PENDING(sock);
+      silc_buffer_clear(sock->outbuf);
       return;
     }
 
@@ -2270,8 +2360,17 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
                       sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
                       "Router")));
 
-      if (sock->user_data)
+      if (sock->user_data) {
+       /* If backup then mark that resuming will not be allowed */
+       if (server->server_type == SILC_ROUTER && !server->backup_router &&
+           sock->type == SILC_SOCKET_TYPE_SERVER) {
+         SilcServerEntry server_entry = sock->user_data;
+         if (server_entry->server_type == SILC_BACKUP_ROUTER)
+           server->backup_closed = TRUE;
+       }
+
        silc_server_free_sock_user_data(server, sock, NULL);
+      }
       SILC_SET_DISCONNECTING(sock);
       silc_server_close_connection(server, sock);
     }
@@ -2292,8 +2391,17 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
                       sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
                       "Router"), strerror(errno)));
 
-      if (sock->user_data)
+      if (sock->user_data) {
+       /* If backup then mark that resuming will not be allowed */
+       if (server->server_type == SILC_ROUTER && !server->backup_router &&
+           sock->type == SILC_SOCKET_TYPE_SERVER) {
+         SilcServerEntry server_entry = sock->user_data;
+         if (server_entry->server_type == SILC_BACKUP_ROUTER)
+           server->backup_closed = TRUE;
+       }
+
        silc_server_free_sock_user_data(server, sock, NULL);
+      }
       SILC_SET_DISCONNECTING(sock);
       silc_server_close_connection(server, sock);
     }
@@ -2318,7 +2426,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     if (sock->user_data) {
       char tmp[128];
 
-      /* If backup disconnected then mark that resuming willl not be allowed */
+      /* If backup disconnected then mark that resuming will not be allowed */
       if (server->server_type == SILC_ROUTER && !server->backup_router &&
          sock->type == SILC_SOCKET_TYPE_SERVER && sock->user_data) {
        SilcServerEntry server_entry = sock->user_data;
@@ -2379,8 +2487,18 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router)
       server->backup_noswitch = TRUE;
 
-    if (sock->user_data)
+    if (sock->user_data) {
+      /* If we are router and backup errorred then mark that resuming
+        will not be allowed */
+      if (server->server_type == SILC_ROUTER && !server->backup_router &&
+         sock->type == SILC_SOCKET_TYPE_SERVER) {
+       SilcServerEntry server_entry = sock->user_data;
+       if (server_entry->server_type == SILC_BACKUP_ROUTER)
+         server->backup_closed = TRUE;
+      }
+
       silc_server_free_sock_user_data(server, sock, NULL);
+    }
     SILC_SET_DISCONNECTING(sock);
     silc_server_close_connection(server, sock);
   }
@@ -2397,6 +2515,11 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   SilcIDListData idata = (SilcIDListData)sock->user_data;
   int ret;
 
+  if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+    SILC_LOG_DEBUG(("Connection is disconnected"));
+    goto out;
+  }
+
   server->stat.packets_received++;
 
   /* Parse the packet */
@@ -2408,8 +2531,10 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
   /* If entry is disabled ignore what we got. */
   if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED &&
       ret != SILC_PACKET_HEARTBEAT && ret != SILC_PACKET_RESUME_ROUTER &&
-      ret != SILC_PACKET_REKEY && ret != SILC_PACKET_REKEY_DONE) {
-    SILC_LOG_DEBUG(("Connection is disabled"));
+      ret != SILC_PACKET_REKEY && ret != SILC_PACKET_REKEY_DONE &&
+      ret != SILC_PACKET_KEY_EXCHANGE_1 && ret != SILC_PACKET_KEY_EXCHANGE_2) {
+    SILC_LOG_DEBUG(("Connection is disabled (packet %s dropped)",
+                   silc_get_packet_name(ret)));
     goto out;
   }
 
@@ -2440,16 +2565,22 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real)
        packet->dst_id_type == SILC_ID_SERVER &&
        sock->type != SILC_SOCKET_TYPE_CLIENT &&
        memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
+      SilcSocketConnection conn;
 
       /* Route the packet to fastest route for the destination ID */
       void *id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
                                packet->dst_id_type);
       if (!id)
        goto out;
-      silc_server_packet_route(server,
-                              silc_server_route_get(server, id,
-                                                    packet->dst_id_type),
-                              packet);
+
+      conn = silc_server_route_get(server, id, packet->dst_id_type);
+      if (!conn) {
+       SILC_LOG_WARNING(("Packet to unknown server ID %s, dropped (no route)",
+                         silc_id_render(id, SILC_ID_SERVER)));
+       goto out;
+      }
+
+      silc_server_packet_route(server, conn, packet);
       silc_free(id);
       goto out;
     }
@@ -2500,6 +2631,11 @@ bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
     silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
                                  parser_context);
 
+    if (SILC_IS_DISCONNECTING(sock) || SILC_IS_DISCONNECTED(sock)) {
+      SILC_LOG_DEBUG(("Connection is disconnected"));
+      return FALSE;
+    }
+
     /* Reprocess data since we'll return FALSE here.  This is because
        the idata->receive_key might have become valid in the last packet
        and we want to call this processor with valid cipher. */
@@ -2547,8 +2683,6 @@ bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
     silc_server_packet_parse_real(server->schedule, server, 0, sock->sock,
                                  parser_context);
     break;
-  default:
-    return TRUE;
   }
 
   return TRUE;
@@ -2594,7 +2728,7 @@ void silc_server_packet_parse_type(SilcServer server,
       /* Do not switch to backup in case of error */
       server->backup_noswitch = (status == SILC_STATUS_OK ? FALSE : TRUE);
 
-      /* If backup disconnected then mark that resuming willl not be allowed */
+      /* If backup disconnected then mark that resuming will not be allowed */
       if (server->server_type == SILC_ROUTER && !server->backup_router &&
          sock->type == SILC_SOCKET_TYPE_SERVER && sock->user_data) {
        SilcServerEntry server_entry = sock->user_data;
@@ -3091,6 +3225,7 @@ SILC_TASK_CALLBACK(silc_server_close_connection_final)
   /* Close the actual connection */
   silc_net_close_connection(sock->sock);
   server->sockets[sock->sock] = NULL;
+  server->stat.conn_num--;
 
   /* We won't listen for this connection anymore */
   silc_schedule_task_del_by_fd(server->schedule, sock->sock);
@@ -3138,6 +3273,7 @@ void silc_server_close_connection(SilcServer server,
                  "Router"), tmp[0] ? tmp : ""));
 
   SILC_SET_DISCONNECTED(sock);
+  silc_socket_set_qos(sock, 0, 0, 0, 0, NULL);
   silc_schedule_task_add(server->schedule, sock->sock,
                         silc_server_close_connection_final,
                         (void *)sock, 0, 1, SILC_TASK_TIMEOUT,
@@ -3256,6 +3392,11 @@ void silc_server_free_client_data(SilcServer server,
   /* Remove this client from watcher list if it is */
   silc_server_del_from_watcher_list(server, client);
 
+  /* Remove this client from the public key hash list */
+  if (client->data.public_key)
+    silc_hash_table_del_by_context(server->pk_hash,
+                                   client->data.public_key, client);
+
   /* Update statistics */
   server->stat.my_clients--;
   server->stat.clients--;
@@ -3271,7 +3412,7 @@ void silc_server_free_client_data(SilcServer server,
   if (!server->server_shutdown) {
     silc_schedule_task_add(server->schedule, 0,
                           silc_server_free_client_data_timeout,
-                          client, 300, 0,
+                          client, 600, 0,
                           SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
     client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
     client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
@@ -3302,6 +3443,8 @@ void silc_server_free_sock_user_data(SilcServer server,
     sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
     silc_protocol_execute_final(sock->protocol, server->schedule);
     sock->protocol = NULL;
+    if (!sock->user_data)
+      return;
   }
 
   switch (sock->type) {
@@ -3475,11 +3618,11 @@ void silc_server_free_sock_user_data(SilcServer server,
        silc_idlist_del_server(server->global_list, user_data);
       if (sock->type == SILC_SOCKET_TYPE_SERVER) {
        server->stat.my_servers--;
+       server->stat.servers--;
       } else {
        server->stat.my_routers--;
        server->stat.routers--;
       }
-      server->stat.servers--;
       if (server->server_type == SILC_ROUTER)
        server->stat.cell_servers--;
 
@@ -4322,8 +4465,12 @@ static void silc_server_announce_get_clients(SilcServer server,
            break;
          continue;
        }
-       if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) &&
-           !client->connection && !client->router && !SILC_IS_LOCAL(client)) {
+       if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
+         if (!silc_idcache_list_next(list, &id_cache))
+           break;
+         continue;
+       }
+       if (!client->connection && !client->router) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          continue;
@@ -4450,7 +4597,7 @@ void silc_server_announce_get_inviteban(SilcServer server,
     type = silc_hash_table_count(channel->invite_list);
     SILC_PUT16_MSB(type, list->data);
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
                                               type);
     silc_hash_table_list_reset(&htl);
@@ -4474,7 +4621,7 @@ void silc_server_announce_get_inviteban(SilcServer server,
     type = silc_hash_table_count(channel->ban_list);
     SILC_PUT16_MSB(type, list->data);
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+    while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2))
       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
                                               type);
     silc_hash_table_list_reset(&htl);
@@ -4503,7 +4650,7 @@ void silc_server_announce_get_channel_users(SilcServer server,
   SilcBuffer chidp, clidp, csidp;
   SilcBuffer tmp, fkey = NULL, chpklist;
   int len;
-  unsigned char mode[4];
+  unsigned char mode[4], ulimit[4];
   char *hmac;
 
   SILC_LOG_DEBUG(("Start"));
@@ -4514,12 +4661,14 @@ void silc_server_announce_get_channel_users(SilcServer server,
 
   /* CMODE notify */
   SILC_PUT32_MSB(channel->mode, mode);
+  if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
+    SILC_PUT32_MSB(channel->user_limit, ulimit);
   hmac = channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : NULL;
   if (channel->founder_key)
     fkey = silc_pkcs_public_key_payload_encode(channel->founder_key);
   tmp =
     silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CMODE_CHANGE,
-                                      7, csidp->data, csidp->len,
+                                      8, csidp->data, csidp->len,
                                       mode, sizeof(mode),
                                       NULL, 0,
                                       hmac, hmac ? strlen(hmac) : 0,
@@ -4529,7 +4678,13 @@ void silc_server_announce_get_channel_users(SilcServer server,
                                       fkey ? fkey->data : NULL,
                                       fkey ? fkey->len : 0,
                                       chpklist ? chpklist->data : NULL,
-                                      chpklist ? chpklist->len : 0);
+                                      chpklist ? chpklist->len : 0,
+                                      (channel->mode &
+                                       SILC_CHANNEL_MODE_ULIMIT ?
+                                       ulimit : NULL),
+                                      (channel->mode &
+                                       SILC_CHANNEL_MODE_ULIMIT ?
+                                       sizeof(ulimit) : 0));
   len = tmp->len;
   *channel_modes =
     silc_buffer_realloc(*channel_modes,
@@ -4903,6 +5058,51 @@ void silc_server_announce_channels(SilcServer server,
   silc_free(channel_ids);
 }
 
+/* Announces WATCH list. */
+
+void silc_server_announce_watches(SilcServer server,
+                                 SilcSocketConnection remote)
+{
+  SilcHashTableList htl;
+  SilcBuffer buffer, idp, args, pkp;
+  SilcClientEntry client;
+  void *key;
+
+  SILC_LOG_DEBUG(("Announcing watch list"));
+
+  /* XXX because way we save the nicks (hash) we cannot announce them. */
+
+  /* XXX we should send all public keys in one command if client is
+     watching more than one key */
+  silc_hash_table_list(server->watcher_list_pk, &htl);
+  while (silc_hash_table_get(&htl, &key, (void *)&client)) {
+    if (!client || !client->id)
+      continue;
+
+    idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+    args = silc_buffer_alloc_size(2);
+    silc_buffer_format(args,
+                      SILC_STR_UI_SHORT(1),
+                      SILC_STR_END);
+    pkp = silc_pkcs_public_key_payload_encode(key);
+    args = silc_argument_payload_encode_one(args, pkp->data, pkp->len, 0x00);
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_WATCH,
+                                           ++server->cmd_ident, 2,
+                                           1, idp->data, idp->len,
+                                           4, args->data, args->len);
+
+    /* Send command */
+    silc_server_packet_send(server, remote, SILC_PACKET_COMMAND, 0,
+                           buffer->data, buffer->len, TRUE);
+
+    silc_buffer_free(pkp);
+    silc_buffer_free(args);
+    silc_buffer_free(idp);
+    silc_buffer_free(buffer);
+  }
+  silc_hash_table_list_reset(&htl);
+}
+
 /* Assembles user list and users mode list from the `channel'. */
 
 bool silc_server_get_users_on_channel(SilcServer server,
@@ -5143,7 +5343,7 @@ void silc_server_save_user_channels(SilcServer server,
      are no part of the list. */
   if (ht) {
     silc_hash_table_list(client->channels, &htl);
-    while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+    while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
       if (!silc_hash_table_find(ht, chl->channel, NULL, NULL)) {
        silc_hash_table_del(chl->channel->user_list, chl->client);
        silc_hash_table_del(chl->client->channels, chl->channel);
@@ -5154,7 +5354,7 @@ void silc_server_save_user_channels(SilcServer server,
     silc_hash_table_free(ht);
   } else {
     silc_hash_table_list(client->channels, &htl);
-    while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+    while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
       silc_hash_table_del(chl->channel->user_list, chl->client);
       silc_hash_table_del(chl->client->channels, chl->channel);
       silc_free(chl);
@@ -5241,7 +5441,7 @@ silc_server_get_client_route(SilcServer server,
       dst_sock = silc_server_route_get(server, id, SILC_ID_CLIENT);
 
       silc_free(id);
-      if (idata)
+      if (idata && dst_sock)
        *idata = (SilcIDListData)dst_sock->user_data;
       return dst_sock;
     }
@@ -5356,6 +5556,16 @@ SILC_TASK_CALLBACK(silc_server_rekey_timeout)
     silc_ske_free(ctx->ske);
   silc_socket_free(sock);
   silc_free(ctx);
+
+  /* Disconnect since we failed to rekey, the keys are probably wrong. */
+  silc_server_disconnect_remote(server, sock,
+                               SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+  if (sock->user_data)
+    silc_server_free_sock_user_data(server, sock, NULL);
+
+  /* Reconnect */
+  if (sock->type != SILC_SOCKET_TYPE_CLIENT)
+    silc_server_create_connections(server);
 }
 
 /* A timeout callback for the re-key. We will be the initiator of the
@@ -5418,7 +5628,10 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_callback)
     silc_schedule_task_add(server->schedule, sock->sock,
                           silc_server_rekey_timeout,
                           proto_ctx,
-                          server->config->key_exchange_timeout, 0,
+                          (idata->rekey->timeout >
+                           server->config->key_exchange_timeout ?
+                           idata->rekey->timeout :
+                           server->config->key_exchange_timeout * 4), 0,
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_LOW);
 
@@ -5457,6 +5670,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
     silc_free(ctx);
     silc_server_disconnect_remote(server, sock,
                                  SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL);
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
 
     /* Reconnect */
     if (sock->type != SILC_SOCKET_TYPE_CLIENT)
index 8cdf3b0352f35603cc4f4520f8a4d7f5b80628d4..55e5f1fc0f0e6e708d08b1c97f4a3faaaf9b7c78 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -222,6 +221,8 @@ void silc_server_announce_clients(SilcServer server,
 void silc_server_announce_channels(SilcServer server,
                                   unsigned long creation_time,
                                   SilcSocketConnection remote);
+void silc_server_announce_watches(SilcServer server,
+                                 SilcSocketConnection remote);
 bool silc_server_get_users_on_channel(SilcServer server,
                                      SilcChannelEntry channel,
                                      SilcBuffer *user_list,
index dce3c9be2d41ff4300f769d0920ab902bf3758dd..160997b5f0384e41077a4cd734953f68f04ea920 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2003 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -22,6 +22,9 @@
 #include "server_internal.h"
 
 SILC_TASK_CALLBACK(silc_server_protocol_backup_done);
+SILC_TASK_CALLBACK(silc_server_backup_connect_to_router);
+SILC_TASK_CALLBACK(silc_server_backup_announce_watches);
+
 static void silc_server_backup_connect_primary(SilcServer server,
                                               SilcServerEntry server_entry,
                                               void *context);
@@ -67,6 +70,7 @@ typedef struct {
   SilcUInt8 session;
   SilcServerBackupProtocolSession *sessions;
   SilcUInt32 sessions_count;
+  SilcUInt32 initiator_restart;
   long start;
   unsigned int responder        : 1;
   unsigned int received_failure : 1;
@@ -293,7 +297,6 @@ void silc_server_backup_replaced_del(SilcServer server,
     if (server->backup->replaced[i]->server == server_entry) {
       silc_free(server->backup->replaced[i]);
       server->backup->replaced[i] = NULL;
-      return;
     }
   }
 }
@@ -688,6 +691,8 @@ void silc_server_backup_resume_router(SilcServer server,
       unsigned char data[4];
       SILC_LOG_DEBUG(("Backup resuming not allowed since we are still "
                      "primary router"));
+      SILC_LOG_INFO(("Backup resuming not allowed since we are still "
+                    "primary router"));
       SILC_PUT32_MSB(SILC_SERVER_BACKUP_START, data);
       silc_server_packet_send(server, sock, SILC_PACKET_FAILURE, 0,
                              data, 4, FALSE);
@@ -778,6 +783,46 @@ void silc_server_backup_resume_router(SilcServer server,
   }
 }
 
+/* callback for async connection to remote router */
+
+SILC_TASK_CALLBACK(silc_server_backup_connection_established)
+{
+  SilcServer server = app_context;
+  SilcServerConnection sconn = (SilcServerConnection)context;
+  int sock = fd;
+  int opt = EINVAL, optlen = sizeof(opt);
+
+  silc_schedule_task_del_by_fd(server->schedule, sock);
+  silc_schedule_unset_listen_fd(server->schedule, sock);
+
+  if (silc_net_get_socket_opt(sock, SOL_SOCKET, SO_ERROR, &opt, &optlen) ||
+      (opt != 0)) {
+    SILC_LOG_DEBUG(("Could not connect to router %s:%d: %s", sconn->remote_host,
+                   sconn->remote_port, strerror(opt)));
+
+    if (server->server_type == SILC_SERVER) {
+      sconn->retry_count++;
+      if (sconn->retry_count > 3) {
+       silc_free(sconn->remote_host);
+       silc_free(sconn);
+       return;
+      }
+    }
+    silc_schedule_task_add(server->schedule, 0,
+                          silc_server_backup_connect_to_router,
+                          context, 10, 0, SILC_TASK_TIMEOUT,
+                          SILC_TASK_PRI_NORMAL);
+    return;
+  }
+
+  SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
+                 sconn->remote_port));
+
+  /* Continue with key exchange protocol */
+  silc_server_start_key_exchange(server, sconn, sock);
+}
+
+
 /* Timeout task callback to connect to remote router */
 
 SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
@@ -793,8 +838,8 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
   /* Connect to remote host */
   server_ip = server->config->server_info->primary == NULL ? NULL :
     server->config->server_info->primary->server_ip;
-  sock = silc_net_create_connection(server_ip, sconn->remote_port,
-                                   sconn->remote_host);
+  sock = silc_net_create_connection_async(server_ip, sconn->remote_port,
+                                         sconn->remote_host);
   if (sock < 0) {
     if (server->server_type == SILC_SERVER) {
       sconn->retry_count++;
@@ -811,8 +856,13 @@ SILC_TASK_CALLBACK(silc_server_backup_connect_to_router)
     return;
   }
 
-  /* Continue with key exchange protocol */
-  silc_server_start_key_exchange(server, sconn, sock);
+  /* wait for the connection to be established */
+  silc_schedule_task_add(server->schedule, sock,
+                        silc_server_backup_connection_established,
+                        context, 0, 0, SILC_TASK_FD,
+                        SILC_TASK_PRI_NORMAL);
+  silc_schedule_set_listen_fd(server->schedule, sock,
+                             SILC_TASK_WRITE, FALSE);
 }
 
 /* Constantly tries to reconnect to a primary router indicated by the
@@ -856,7 +906,7 @@ SILC_TASK_CALLBACK(silc_server_backup_connected_later)
     SILC_LOG_DEBUG(("Other protocol is running, wait for it to finish"));
     silc_schedule_task_add(server->schedule, 0,
                           silc_server_backup_connected_later,
-                          proto_ctx, 10, 0,
+                          proto_ctx, 15, 0,
                           SILC_TASK_TIMEOUT,
                           SILC_TASK_PRI_NORMAL);
     return;
@@ -1256,6 +1306,12 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
       SILC_LOG_INFO(("We are now the primary router of our cell again"));
       server->wait_backup = FALSE;
 
+      /* Announce WATCH list a little later */
+      silc_schedule_task_add(server->schedule, 0,
+                            silc_server_backup_announce_watches,
+                            silc_socket_dup(ctx->sock), 4, 0,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+
       /* For us this is the end of this protocol. */
       if (protocol->final_callback)
        silc_protocol_execute_final(protocol, server->schedule);
@@ -1410,6 +1466,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
            ctx->sock = NULL;
          }
 
+         /* If failed after 10 attempts, it won't work, give up */
+         if (ctx->initiator_restart > 10)
+           ctx->received_failure = TRUE;
+
          if (!ctx->received_failure) {
            /* Protocol error, probably timeout. Just restart the protocol. */
            SilcServerBackupProtocolContext proto_ctx;
@@ -1421,11 +1481,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
            proto_ctx->responder = FALSE;
            proto_ctx->type = SILC_SERVER_BACKUP_START;
            proto_ctx->start = time(0);
+           proto_ctx->initiator_restart = ctx->initiator_restart + 1;
 
            /* Start through scheduler */
            silc_schedule_task_add(server->schedule, 0,
                                   silc_server_backup_connected_later,
-                                  proto_ctx, 2, 0,
+                                  proto_ctx, 5, 0,
                                   SILC_TASK_TIMEOUT,
                                   SILC_TASK_PRI_NORMAL);
          } else {
@@ -1443,6 +1504,13 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
            /* Announce our clients and channels to the router */
            silc_server_announce_clients(server, 0, sock);
            silc_server_announce_channels(server, 0, sock);
+
+           /* Announce WATCH list a little later */
+           silc_schedule_task_add(server->schedule, 0,
+                                  silc_server_backup_announce_watches,
+                                  silc_socket_dup(sock), 5, 0,
+                                  SILC_TASK_TIMEOUT,
+                                  SILC_TASK_PRI_NORMAL);
          }
 
          continue;
@@ -1465,6 +1533,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
       /* Announce our clients and channels to the router */
       silc_server_announce_clients(server, 0, server->router->connection);
       silc_server_announce_channels(server, 0, server->router->connection);
+
+      /* Announce WATCH list a little later */
+      silc_schedule_task_add(server->schedule, 0,
+                            silc_server_backup_announce_watches,
+                            silc_socket_dup(server->router->connection), 4, 0,
+                            SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
     }
   } else {
     /* Error */
@@ -1506,3 +1580,12 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
   silc_free(ctx->sessions);
   silc_free(ctx);
 }
+
+SILC_TASK_CALLBACK(silc_server_backup_announce_watches)
+{
+  SilcSocketConnection sock = context;
+  SilcServer server = app_context;
+  if (sock->users > 1)
+    silc_server_announce_watches(server, sock);
+  silc_socket_free(sock);
+}
index 7cf42a8ed8964553455acac8f70a10e81438c231..ebbeadab6be30a6f35f6343e6f70271247206f03 100644 (file)
@@ -61,6 +61,7 @@ typedef struct {
   SilcUInt32 auth_failures;              /* Authentication failures */
   SilcUInt32 packets_sent;               /* Sent SILC packets */
   SilcUInt32 packets_received;           /* Received SILC packets */
+  SilcUInt32 conn_num;                   /* Number of connections */
 } SilcServerStatistics;
 
 /*
@@ -111,6 +112,7 @@ struct SilcServerStruct {
   SilcIDList local_list;
   SilcIDList global_list;
   SilcHashTable watcher_list;
+  SilcHashTable watcher_list_pk;
 
   /* Table of connected sockets */
   SilcSocketConnection *sockets;
@@ -146,6 +148,9 @@ struct SilcServerStruct {
   /* SIM (SILC Module) list */
   SilcDList sim;
 #endif
+
+  /* Hash table for public keys of all clients */
+  SilcHashTable pk_hash;
 };
 
 /* Failure context. This is allocated when failure packet is received.
index 3414c650c517afce54047277d32eab873454dfa7..a248600953631b6993644b96b3a47a42a334ee81 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 - 2003 Pekka Riikonen
+  Copyright (C) 2002 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -42,19 +42,19 @@ typedef struct {
 typedef struct {
   void *id;                        /* ID */
   SilcIdType id_type;              /* ID type */
-  SilcUInt16 index;                /* Index to IDs */
-  unsigned int from_cmd : 1;               /* TRUE if `index' is from command args,
-                                      otherwise from query->ids */
+  unsigned int index : 15;         /* Index to IDs */
+  unsigned int type : 2;           /* 0 = take from query->ids, 1 = take
+                                      from args, 2 = no args in error. */
   unsigned int error : 7;          /* The actual error (SilcStatus) */
 } *SilcServerQueryError;
 
 /* Query session context */
 typedef struct {
   /* Queried data */
-  char *nickname;                  /* Queried nickname */
+  char *nickname;                  /* Queried nickname, normalized */
   char *nick_server;               /* Queried nickname's server */
-  char *server_name;               /* Queried server name */
-  char *channel_name;              /* Queried channel name */
+  char *server_name;               /* Queried server name, normalized */
+  char *channel_name;              /* Queried channel name, normalized */
   SilcServerQueryID ids;           /* Queried IDs */
   SilcUInt32 ids_count;                    /* number of queried IDs */
   SilcUInt32 reply_count;          /* Requested reply count */
@@ -80,7 +80,7 @@ void silc_server_query_send_error(SilcServer server,
                                  SilcStatus error, ...);
 void silc_server_query_add_error(SilcServer server,
                                 SilcServerQuery query,
-                                bool from_cmd,
+                                SilcUInt32 type,
                                 SilcUInt32 index,
                                 SilcStatus error);
 void silc_server_query_add_error_id(SilcServer server,
@@ -173,11 +173,13 @@ void silc_server_query_send_error(SilcServer server,
    processing and this function can be used to add one error.  The
    `index' is the index to the command context which includes the argument
    which caused the error, or it is the index to query->ids, depending
-   on value of `from_cmd'. */
+   on value of `type'.  If `type' is 0 the index is to query->ids, if
+   it is 1 it is index to the command context arguments, and if it is
+   2 the index is ignored and no argument is included in the error. */
 
 void silc_server_query_add_error(SilcServer server,
                                 SilcServerQuery query,
-                                bool from_cmd,
+                                SilcUInt32 type,
                                 SilcUInt32 index,
                                 SilcStatus error)
 {
@@ -186,7 +188,7 @@ void silc_server_query_add_error(SilcServer server,
   if (!query->errors)
     return;
   query->errors[query->errors_count].index = index;
-  query->errors[query->errors_count].from_cmd = from_cmd;
+  query->errors[query->errors_count].type = type;
   query->errors[query->errors_count].error = error;
   query->errors[query->errors_count].id = NULL;
   query->errors[query->errors_count].id_type = 0;
@@ -206,7 +208,7 @@ void silc_server_query_add_error_id(SilcServer server,
   if (!query->errors)
     return;
   query->errors[query->errors_count].index = 0;
-  query->errors[query->errors_count].from_cmd = FALSE;
+  query->errors[query->errors_count].type = 0;
   query->errors[query->errors_count].error = error;
   query->errors[query->errors_count].id = silc_id_dup(id, id_type);
   query->errors[query->errors_count].id_type = id_type;
@@ -234,11 +236,15 @@ bool silc_server_query_command(SilcServer server, SilcCommand querycmd,
   switch (querycmd) {
 
   case SILC_COMMAND_WHOIS:
-    /* If we are normal server and query contains nickname, send it
-       directly to router. */
-    if (server->server_type == SILC_SERVER && !server->standalone &&
+    /* If we are normal server and query contains nickname OR query
+       doesn't contain nickname or ids BUT attributes, send it to the
+       router */
+    if (server->server_type != SILC_ROUTER && !server->standalone &&
        cmd->sock != SILC_PRIMARY_ROUTE(server) &&
-       silc_argument_get_arg_type(cmd->args, 1, NULL)) {
+        (silc_argument_get_arg_type(cmd->args, 1, NULL) ||
+        (!silc_argument_get_arg_type(cmd->args, 1, NULL) &&
+         !silc_argument_get_arg_type(cmd->args, 4, NULL) &&
+         silc_argument_get_arg_type(cmd->args, 3, NULL)))) {
       silc_server_query_send_router(server, query);
       return TRUE;
     }
@@ -317,6 +323,13 @@ void silc_server_query_send_router_reply(void *context, void *reply)
 
   SILC_LOG_DEBUG(("Received reply from router to query"));
 
+  /* If the original command caller has gone away, just stop. */
+  if (query->cmd->sock->users == 1) {
+    SILC_LOG_DEBUG(("Original command caller vanished"));
+    silc_server_query_free(query);
+    return;
+  }
+
   /* Check if router sent error reply */
   if (cmdr && !silc_command_get_status(cmdr->payload, NULL, NULL)) {
     SilcBuffer buffer;
@@ -357,13 +370,27 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
   switch (query->querycmd) {
 
   case SILC_COMMAND_WHOIS:
+    /* Get requested attributes if set */
+    tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+    if (tmp && !query->attrs && tmp_len <= SILC_ATTRIBUTE_MAX_REQUEST_LEN) {
+      query->attrs = silc_attribute_payload_parse(tmp, tmp_len);
+
+      /* When Requested Attributes is present we will assure that this
+        client cannot execute the WHOIS command too fast.  This would be
+        same as having SILC_CF_LAG_STRICT. */
+      if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
+          cmd->sock->user_data)
+       ((SilcClientEntry)cmd->sock->user_data)->fast_command = 6;
+    }
+
     /* Get Client IDs if present. Take IDs always instead of nickname. */
     tmp = silc_argument_get_arg_type(cmd->args, 4, &tmp_len);
     if (!tmp) {
 
       /* Get nickname */
       tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-      if (!tmp) {
+      if (!tmp && !query->attrs) {
+       /* No nickname, no ids and no attributes - send error */
        silc_server_query_send_error(server, query,
                                     SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
        silc_server_query_free(query);
@@ -371,13 +398,25 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
       }
 
       /* Get the nickname@server string and parse it */
-      if (tmp_len > 128 ||
-         !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server)) {
+      if (tmp && ((tmp_len > 128) ||
+         !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server))) {
+       silc_server_query_send_error(server, query,
+                                    SILC_STATUS_ERR_BAD_NICKNAME, 0);
+       silc_server_query_free(query);
+       return;
+      }
+
+      /* Check nickname */
+      tmp = silc_identifier_check(query->nickname, strlen(query->nickname),
+                                 SILC_STRING_UTF8, 128, &tmp_len);
+      if (!tmp) {
        silc_server_query_send_error(server, query,
                                     SILC_STATUS_ERR_BAD_NICKNAME, 0);
        silc_server_query_free(query);
        return;
       }
+      silc_free(query->nickname);
+      query->nickname = tmp;
 
     } else {
       /* Parse the IDs included in the query */
@@ -390,7 +429,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
 
        id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
        if (!id || id_type != SILC_ID_CLIENT) {
-         silc_server_query_add_error(server, query, TRUE, i + 4,
+         silc_server_query_add_error(server, query, 1, i + 4,
                                      SILC_STATUS_ERR_BAD_CLIENT_ID);
          continue;
        }
@@ -425,20 +464,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
     tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
     if (tmp && tmp_len == sizeof(SilcUInt32))
       SILC_GET32_MSB(query->reply_count, tmp);
-
-    /* Get requested attributes if set */
-    tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
-    if (tmp && tmp_len <= SILC_ATTRIBUTE_MAX_REQUEST_LEN) {
-      query->attrs = silc_attribute_payload_parse(tmp, tmp_len);
-
-      /* When Requested Attributes is present we will assure that this
-        client cannot execute the WHOIS command too fast.  This would be
-        same as having SILC_CF_LAG_STRICT. */
-      if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
-         cmd->sock->user_data)
-       ((SilcClientEntry)cmd->sock->user_data)->fast_command = 6;
-    }
-    break;
+   break;
 
   case SILC_COMMAND_WHOWAS:
     /* Get nickname */
@@ -459,6 +485,18 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
       return;
     }
 
+    /* Check nickname */
+    tmp = silc_identifier_check(query->nickname, strlen(query->nickname),
+                               SILC_STRING_UTF8, 128, &tmp_len);
+    if (!tmp) {
+      silc_server_query_send_error(server, query,
+                                  SILC_STATUS_ERR_BAD_NICKNAME, 0);
+      silc_server_query_free(query);
+      return;
+    }
+    silc_free(query->nickname);
+    query->nickname = tmp;
+
     /* Get the max count of reply messages allowed */
     tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
     if (tmp && tmp_len == sizeof(SilcUInt32))
@@ -476,19 +514,51 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
        /* Get the nickname@server string and parse it */
        if (tmp_len > 128 ||
            !silc_parse_userfqdn(tmp, &query->nickname, &query->nick_server))
-         silc_server_query_add_error(server, query, TRUE, 1,
+         silc_server_query_add_error(server, query, 1, 1,
                                      SILC_STATUS_ERR_BAD_NICKNAME);
+
+       /* Check nickname */
+       tmp = silc_identifier_check(query->nickname, strlen(query->nickname),
+                                   SILC_STRING_UTF8, 128, &tmp_len);
+       if (!tmp) {
+         silc_server_query_send_error(server, query,
+                                      SILC_STATUS_ERR_BAD_NICKNAME, 0);
+         silc_server_query_free(query);
+         return;
+       }
+       silc_free(query->nickname);
+       query->nickname = tmp;
       }
 
       /* Try get server name */
       tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-      if (tmp)
-       query->server_name = silc_memdup(tmp, tmp_len);
+      if (tmp) {
+       /* Check server name */
+       tmp = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8,
+                                   256, &tmp_len);
+       if (!tmp) {
+         silc_server_query_send_error(server, query,
+                                      SILC_STATUS_ERR_BAD_SERVER, 0);
+         silc_server_query_free(query);
+         return;
+       }
+       query->server_name = tmp;
+      }
 
       /* Get channel name */
       tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
-      if (tmp && tmp_len <= 256)
-       query->channel_name = silc_memdup(tmp, tmp_len);
+      if (tmp && tmp_len <= 256) {
+       /* Check channel name */
+       tmp = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8,
+                                   256, &tmp_len);
+       if (!tmp) {
+         silc_server_query_send_error(server, query,
+                                      SILC_STATUS_ERR_BAD_CHANNEL, 0);
+         silc_server_query_free(query);
+         return;
+       }
+       query->channel_name = tmp;
+      }
 
       if (!query->nickname && !query->server_name && !query->channel_name) {
        silc_server_query_send_error(server, query,
@@ -508,7 +578,7 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
 
        id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
        if (!id) {
-         silc_server_query_add_error(server, query, TRUE, i + 5,
+         silc_server_query_add_error(server, query, 1, i + 5,
                                      SILC_STATUS_ERR_BAD_CLIENT_ID);
          continue;
        }
@@ -563,6 +633,115 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
   silc_server_query_process(server, query, TRUE);
 }
 
+/* Context for holding clients searched by public key. */
+typedef struct {
+  SilcClientEntry **clients;
+  SilcUInt32 *clients_count;
+  bool found;
+} *SilcServerPublicKeyUser, SilcServerPublicKeyUserStruct;
+
+void silc_server_public_key_hash_foreach(void *key, void *context,
+                                         void *user_context)
+{
+  SilcServerPublicKeyUser uc = user_context;
+  SilcClientEntry entry = context;
+
+  /* Nothing was found, just return */
+  if (!context)
+    return;
+
+  uc->found = TRUE;
+
+  (*uc->clients) = silc_realloc((*uc->clients),
+                                sizeof((**uc->clients)) *
+                               ((*uc->clients_count) + 1));
+  (*uc->clients)[(*uc->clients_count)++] = entry;
+}
+
+/* If clients are set, limit the found clients using the attributes in
+   the query. If clients are not set, try to find some clients using
+   the attributes */
+
+void silc_server_query_check_attributes(SilcServer server,
+                                        SilcServerQuery query,
+                                        SilcClientEntry **clients,
+                                        SilcUInt32 *clients_count) {
+  SilcClientEntry entry;
+  SilcAttributePayload attr;
+  SilcAttribute attribute;
+  SilcAttributeObjPk pk;
+  SilcPublicKey publickey;
+  int i;
+  bool found = FALSE, no_clients = FALSE;
+
+  /* If no clients were found, we only check the attributes
+     if the user wasn't searching for nickname/ids */
+  if (!(*clients)) {
+    no_clients = TRUE;
+    if (query->nickname || query->ids_count)
+      return;
+  }
+
+  silc_dlist_start(query->attrs);
+  while ((attr = silc_dlist_get(query->attrs)) != SILC_LIST_END) {
+    attribute = silc_attribute_get_attribute(attr);
+    switch (attribute) {
+
+      case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
+       SILC_LOG_DEBUG(("Finding clients by public key attribute"));
+
+       if (!silc_attribute_get_object(attr, &pk, sizeof(pk)))
+         continue;
+
+       if (!silc_pkcs_public_key_decode(pk.data, pk.data_len,
+                                        &publickey)) {
+         silc_free(pk.type);
+         silc_free(pk.data);
+         continue;
+       }
+
+       /* If no clients were set on calling this function, we
+          just search for clients, otherwise we try to limit
+          the clients */
+       if (no_clients) {
+         SilcServerPublicKeyUserStruct usercontext;
+
+         usercontext.clients = clients;
+         usercontext.clients_count = clients_count;
+         usercontext.found = FALSE;
+
+         silc_hash_table_find_foreach(server->pk_hash, publickey,
+                                      silc_server_public_key_hash_foreach,
+                                      &usercontext);
+
+         if (usercontext.found == TRUE)
+           found = TRUE;
+       } else {
+         for (i = 0; i < *clients_count; i++) {
+           entry = (*clients)[i];
+
+           if (!entry->data.public_key)
+             continue;
+
+           if (!silc_hash_table_find_by_context(server->pk_hash, publickey,
+                                                entry, NULL))
+             (*clients)[i] = NULL;
+           else
+             found = TRUE;
+         }
+       }
+       silc_free(pk.type);
+       silc_free(pk.data);
+       silc_pkcs_public_key_free(publickey);
+       break;
+    }
+  }
+
+  if (!found && !query->nickname && !query->ids)
+    silc_server_query_add_error(server, query, 2, 0,
+                                SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+}
+
 /* Processes the parsed query.  This does the actual finding of the
    queried information and prepares for sending reply to the original
    sender of the query command. */
@@ -611,7 +790,7 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
     }
 
     if (!clients)
-      silc_server_query_add_error(server, query, TRUE, 1,
+      silc_server_query_add_error(server, query, 1, 1,
                                  SILC_STATUS_ERR_NO_SUCH_NICK);
   }
 
@@ -628,7 +807,7 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
     }
 
     if (!servers)
-      silc_server_query_add_error(server, query, TRUE, 2,
+      silc_server_query_add_error(server, query, 1, 2,
                                  SILC_STATUS_ERR_NO_SUCH_SERVER);
   }
 
@@ -646,7 +825,7 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
     }
 
     if (!channels)
-      silc_server_query_add_error(server, query, TRUE, 3,
+      silc_server_query_add_error(server, query, 1, 3,
                                  SILC_STATUS_ERR_NO_SUCH_CHANNEL);
   }
 
@@ -667,7 +846,7 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
          entry = silc_idlist_find_client_by_id(server->global_list,
                                                id, TRUE, NULL);
        if (!entry) {
-         silc_server_query_add_error(server, query, FALSE, i,
+         silc_server_query_add_error(server, query, 0, i,
                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
          continue;
        }
@@ -685,7 +864,7 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
          entry = silc_idlist_find_server_by_id(server->global_list,
                                                id, TRUE, NULL);
        if (!entry) {
-         silc_server_query_add_error(server, query, FALSE, i,
+         silc_server_query_add_error(server, query, 0, i,
                                      SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
          continue;
        }
@@ -702,7 +881,7 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
          entry = silc_idlist_find_channel_by_id(server->global_list, id,
                                                 NULL);
        if (!entry) {
-         silc_server_query_add_error(server, query, FALSE, i,
+         silc_server_query_add_error(server, query, 0, i,
                                      SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
          continue;
        }
@@ -718,6 +897,11 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
     }
   }
 
+  /* Check the attributes to narrow down the search by using them. */
+  if (query->attrs)
+    silc_server_query_check_attributes(server, query, &clients,
+                                       &clients_count);
+
   SILC_LOG_DEBUG(("Querying %d clients", clients_count));
   SILC_LOG_DEBUG(("Querying %d servers", servers_count));
   SILC_LOG_DEBUG(("Querying %d channels", channels_count));
@@ -788,6 +972,11 @@ void silc_server_query_process(SilcServer server, SilcServerQuery query,
           client_entry->data.status & SILC_IDLIST_STATUS_NOATTR))
        continue;
 
+      /* If attributes are present in query, and in the entry and we have
+        done resolvings already we don't need to resolve anymore */
+      if (query->resolved && query->attrs && client_entry->attrs)
+       continue;
+
       /* Resolve the detailed client information. If client is local we
         know that attributes were present and we will resolve directly
         from the client. Otherwise resolve from client's owner. */
@@ -1099,6 +1288,13 @@ void silc_server_query_resolve_reply(void *context, void *reply)
 
   SILC_LOG_DEBUG(("Reprocess the query"));
 
+  /* If the original command caller has gone away, just stop. */
+  if (query->cmd->sock->users == 1) {
+    SILC_LOG_DEBUG(("Original command caller vanished"));
+    silc_server_query_free(query);
+    return;
+  }
+
   /* We have received all queries.  Now re-search all information required
      to complete this query.  Reason we cannot save the values found in
      the first search is that SilcClientEntry, SilcServerEntry and
@@ -1132,7 +1328,7 @@ void silc_server_query_send_reply(SilcServer server,
   SilcUInt32 len;
   SilcBuffer idp;
   int i, k, valid_count;
-  char nh[256], uh[256];
+  char nh[384], uh[384];
   bool sent_reply = FALSE;
 
   SILC_LOG_DEBUG(("Sending reply to query"));
@@ -1151,6 +1347,9 @@ void silc_server_query_send_reply(SilcServer server,
     /* Mark all invalid entries */
     for (i = 0, valid_count = 0; i < clients_count; i++) {
       entry = clients[i];
+      if (!entry)
+       continue;
+
       switch (query->querycmd) {
       case SILC_COMMAND_WHOIS:
        if (!entry->nickname || !entry->username || !entry->userinfo ||
@@ -1217,7 +1416,6 @@ void silc_server_query_send_reply(SilcServer server,
                       "      : "), entry->nickname));
 
       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
-      memset(uh, 0, sizeof(uh));
       memset(nh, 0, sizeof(nh));
 
       silc_strncat(nh, sizeof(nh), entry->nickname, strlen(entry->nickname));
@@ -1245,6 +1443,8 @@ void silc_server_query_send_reply(SilcServer server,
 
          memset(fempty, 0, sizeof(fempty));
          memset(idle, 0, sizeof(idle));
+         memset(uh, 0, sizeof(uh));
+
          silc_strncat(uh, sizeof(uh), entry->username,
                       strlen(entry->username));
          if (!strchr(entry->username, '@') && entry->connection) {
@@ -1278,8 +1478,8 @@ void silc_server_query_send_reply(SilcServer server,
          if (query->attrs) {
            if (!entry->attrs && SILC_IS_LOCAL(entry)) {
              tmpattrs = silc_server_query_reply_attrs(server, query, entry);
-             entry->attrs = silc_memdup(tmpattrs->data, tmpattrs->len);
-             entry->attrs_len = tmpattrs->len;
+             entry->attrs = silc_buffer_steal(tmpattrs, &len);
+             entry->attrs_len = len;
              silc_buffer_free(tmpattrs);
            }
            attrs = entry->attrs;
@@ -1353,7 +1553,7 @@ void silc_server_query_send_reply(SilcServer server,
       case SILC_COMMAND_WHOWAS:
        silc_strncat(uh, sizeof(uh), entry->username, strlen(entry->username));
        if (!strchr(entry->username, '@'))
-         silc_strncat(uh, sizeof(uh), "@*private*", 10);
+         silc_strncat(uh, sizeof(uh), "@-private-", 10);
 
        /* Send command reply */
        silc_server_send_command_reply(server, cmd->sock, query->querycmd,
@@ -1379,9 +1579,14 @@ void silc_server_query_send_reply(SilcServer server,
       /* Not one valid entry was found, send error.  If nickname was used
         in query send error based on that, otherwise the query->errors
         already includes proper errors. */
-      if (query->nickname)
-       silc_server_query_add_error(server, query, TRUE, 1,
+      if (query->nickname || (!query->ids && query->attrs))
+       silc_server_query_add_error(server, query, 1, 1,
                                    SILC_STATUS_ERR_NO_SUCH_NICK);
+
+      /* Make sure some error is sent */
+      if (!query->errors_count && !servers_count && !channels_count)
+       silc_server_query_add_error(server, query, 2, 0,
+                                   SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     }
   }
 
@@ -1491,15 +1696,19 @@ void silc_server_query_send_reply(SilcServer server,
       idp = NULL;
 
       /* Take error argument */
-      if (query->errors[i].from_cmd) {
+      if (query->errors[i].type == 1) {
+       /* Take from sent arguments */
        len = 0;
        tmp = silc_argument_get_arg_type(cmd->args,
                                         query->errors[i].index, &len);
-       if (query->errors[i].index == 1)
-         type = 3;                 /* Nickname */
-       else
-         type = 2;                 /* ID */
+       type = 2;
+      } else if (query->errors[i].type == 2) {
+       /* No argument */
+       len = 0;
+       tmp = NULL;
+       type = 0;
       } else if (!query->errors[i].id) {
+       /* Take from query->ids */
        idp =
          silc_id_payload_encode(query->ids[query->errors[i].index].id,
                                 query->ids[query->errors[k].index].id_type);
@@ -1507,6 +1716,7 @@ void silc_server_query_send_reply(SilcServer server,
        len = idp->len;
        type = 2;
       } else {
+       /* Take added ID. */
        idp = silc_id_payload_encode(query->errors[i].id,
                                     query->errors[k].id_type);
        tmp = idp->data;
@@ -1532,6 +1742,18 @@ void silc_server_query_send_reply(SilcServer server,
                      silc_get_status_message(query->errors[i].error),
                      query->errors[i].error));
 
+#if 1 /* XXX Backwards compatibility.  Remove in 1.0. */
+      if (query->errors[i].error == SILC_STATUS_ERR_NO_SUCH_NICK)
+       /* Send error */
+       silc_server_send_command_reply(server, cmd->sock, query->querycmd,
+                                      (status == SILC_STATUS_OK ?
+                                       query->errors[i].error : status),
+                                      (status == SILC_STATUS_OK ?
+                                       0 : query->errors[i].error), ident, 2,
+                                      type, tmp, len,
+                                      3, tmp, len);
+      else
+#endif
       /* Send error */
       silc_server_send_command_reply(server, cmd->sock, query->querycmd,
                                     (status == SILC_STATUS_OK ?
@@ -1539,6 +1761,7 @@ void silc_server_query_send_reply(SilcServer server,
                                     (status == SILC_STATUS_OK ?
                                      0 : query->errors[i].error), ident, 1,
                                     type, tmp, len);
+
       silc_buffer_free(idp);
       sent_reply = TRUE;
 
index 2cc4907804fabca8ebffc23fe4fb2b43de50d6aa..46cf87aa619cf6f9e4d5bb7a77d0b722dc1d1d7e 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -52,7 +52,7 @@ silc_server_remove_clients_channels(SilcServer server,
   /* Remove the client from all channels. The client is removed from
      the channels' user list. */
   silc_hash_table_list(client->channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     channel = chl->channel;
 
     /* Remove channel if this is last client leaving the channel, unless
@@ -101,7 +101,7 @@ silc_server_remove_clients_channels(SilcServer server,
     /* Mark other local clients to the table of clients whom will receive
        the SERVER_SIGNOFF notify. */
     silc_hash_table_list(channel->user_list, &htl2);
-    while (silc_hash_table_get(&htl2, NULL, (void **)&chl2)) {
+    while (silc_hash_table_get(&htl2, NULL, (void *)&chl2)) {
       SilcClientEntry c = chl2->client;
       if (!c)
        continue;
@@ -119,6 +119,7 @@ silc_server_remove_clients_channels(SilcServer server,
       silc_hash_table_add(channels, channel, channel);
   }
   silc_hash_table_list_reset(&htl);
+  assert(!silc_hash_table_count(client->channels));
 }
 
 /* This function removes all client entries that are originated from
@@ -211,6 +212,10 @@ bool silc_server_remove_clients_by_server(SilcServer server,
        SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
        SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
 
+       if (client->data.public_key)
+         silc_hash_table_del_by_context(server->pk_hash,
+                                        client->data.public_key,
+                                        client);
        silc_server_remove_clients_channels(server, entry, clients,
                                            client, channels);
        silc_server_del_from_watcher_list(server, client);
@@ -218,6 +223,9 @@ bool silc_server_remove_clients_by_server(SilcServer server,
        /* Remove the client entry */
        if (!server_signoff) {
          client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+         client->mode = 0;
+         client->router = NULL;
+         client->connection = NULL;
          id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
        } else {
          silc_idlist_del_data(client);
@@ -271,6 +279,10 @@ bool silc_server_remove_clients_by_server(SilcServer server,
        SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
        SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
 
+       if (client->data.public_key)
+         silc_hash_table_del_by_context(server->pk_hash,
+                                        client->data.public_key,
+                                        client);
        silc_server_remove_clients_channels(server, entry, clients,
                                            client, channels);
        silc_server_del_from_watcher_list(server, client);
@@ -278,6 +290,9 @@ bool silc_server_remove_clients_by_server(SilcServer server,
        /* Remove the client entry */
        if (!server_signoff) {
          client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+         client->mode = 0;
+         client->router = NULL;
+         client->connection = NULL;
          id_cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
        } else {
          silc_idlist_del_data(client);
@@ -352,7 +367,7 @@ bool silc_server_remove_clients_by_server(SilcServer server,
      this server's client(s) on the channel. As they left the channel we
      must re-generate the channel key. */
   silc_hash_table_list(channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&channel)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&channel)) {
     if (!silc_server_create_channel_key(server, channel, 0)) {
       silc_hash_table_list_reset(&htl);
       silc_hash_table_free(channels);
@@ -542,7 +557,7 @@ void silc_server_update_clients_by_server(SilcServer server,
 
        SILC_LOG_DEBUG(("Client %s",
                        silc_id_render(client->id, SILC_ID_CLIENT)));
-       if (client->router)
+       if (client->router && client->router->id)
          SILC_LOG_DEBUG(("Client->router %s",
                          silc_id_render(client->router->id, SILC_ID_SERVER)));
 
@@ -575,7 +590,7 @@ void silc_server_update_clients_by_server(SilcServer server,
          client->router = to;
        }
 
-       if (client->router)
+       if (client->router && client->router->id)
          SILC_LOG_DEBUG(("Client changed to %s",
                          silc_id_render(client->router->id, SILC_ID_SERVER)));
 
@@ -605,7 +620,7 @@ void silc_server_update_clients_by_server(SilcServer server,
 
        SILC_LOG_DEBUG(("Client %s",
                        silc_id_render(client->id, SILC_ID_CLIENT)));
-       if (client->router)
+       if (client->router && client->router->id)
          SILC_LOG_DEBUG(("Client->router %s",
                          silc_id_render(client->router->id, SILC_ID_SERVER)));
 
@@ -634,7 +649,7 @@ void silc_server_update_clients_by_server(SilcServer server,
          client->router = to;
        }
 
-       if (client->router)
+       if (client->router && client->router->id)
          SILC_LOG_DEBUG(("Client changed to %s",
                          silc_id_render(client->router->id, SILC_ID_SERVER)));
 
@@ -864,6 +879,7 @@ void silc_server_remove_servers_by_server(SilcServer server,
                                               TRUE);
 
        /* Remove the server */
+       silc_server_backup_del(server, server_entry);
        silc_idlist_del_server(server->local_list, server_entry);
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -891,6 +907,7 @@ void silc_server_remove_servers_by_server(SilcServer server,
                                               TRUE);
 
        /* Remove the server */
+       silc_server_backup_del(server, server_entry);
        silc_idlist_del_server(server->global_list, server_entry);
 
        if (!silc_idcache_list_next(list, &id_cache))
@@ -966,7 +983,7 @@ bool silc_server_channel_has_global(SilcChannelEntry channel)
   SilcHashTableList htl;
 
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     if (chl->client->router) {
       silc_hash_table_list_reset(&htl);
       return TRUE;
@@ -986,7 +1003,7 @@ bool silc_server_channel_has_local(SilcChannelEntry channel)
   SilcHashTableList htl;
 
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chl)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chl)) {
     if (SILC_IS_LOCAL(chl->client)) {
       silc_hash_table_list_reset(&htl);
       return TRUE;
@@ -1009,6 +1026,8 @@ bool silc_server_channel_delete(SilcServer server,
   SilcHashTableList htl;
   bool delchan = !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH);
 
+  SILC_LOG_DEBUG(("Deleting channel %s", channel->channel_name));
+
   if (delchan) {
     /* Update statistics */
     if (server->server_type == SILC_ROUTER)
@@ -1016,6 +1035,7 @@ bool silc_server_channel_delete(SilcServer server,
 
     /* Totally delete the channel and all users on the channel. The
        users are deleted automatically in silc_idlist_del_channel. */
+    channel->disabled = TRUE;
     silc_schedule_task_del_by_context(server->schedule, channel->rekey);
     if (silc_idlist_del_channel(server->local_list, channel)) {
       server->stat.my_channels--;
@@ -1052,7 +1072,7 @@ bool silc_server_channel_delete(SilcServer server,
   }
   silc_hash_table_list_reset(&htl);
 
-  SILC_LOG_DEBUG(("Channel %s remains", channel->channel_name));
+  SILC_LOG_DEBUG(("Channel %s remains (permanent)", channel->channel_name));
 
   return TRUE;
 }
@@ -1070,7 +1090,7 @@ bool silc_server_client_on_channel(SilcClientEntry client,
     return FALSE;
 
   return silc_hash_table_find(client->channels, channel, NULL,
-                             (void **)chl);
+                             (void *)chl);
 }
 
 /* Checks string for bad characters and returns TRUE if they are found. */
@@ -1193,7 +1213,7 @@ SilcPublicKey silc_server_find_public_key(SilcServer server,
                  silc_hash_table_count(local_public_keys)));
 
   if (!silc_hash_table_find_ext(local_public_keys, remote_public_key,
-                               (void **)&cached_key, NULL,
+                               (void *)&cached_key, NULL,
                                silc_hash_public_key, NULL,
                                silc_hash_public_key_compare, NULL)) {
     SILC_LOG_ERROR(("Public key not found"));
@@ -1221,7 +1241,7 @@ SilcPublicKey silc_server_get_public_key(SilcServer server,
   assert(silc_hash_table_count(local_public_keys) < 2);
 
   silc_hash_table_list(local_public_keys, &htl);
-  if (!silc_hash_table_get(&htl, NULL, (void **)&cached_key)) {
+  if (!silc_hash_table_get(&htl, NULL, (void *)&cached_key)) {
     silc_hash_table_list_reset(&htl);
     return NULL;
   }
@@ -1527,7 +1547,7 @@ void silc_server_send_connect_notifys(SilcServer server,
 
   if (server->stat.cell_clients && server->stat.cell_servers + 1)
     SILC_SERVER_SEND_NOTIFY(server, sock, SILC_NOTIFY_TYPE_NONE,
-                           ("There are %d clients on %d server in our cell",
+                           ("There are %d clients on %d servers in our cell",
                             server->stat.cell_clients,
                             server->stat.cell_servers));
   if (server->server_type == SILC_ROUTER) {
@@ -1634,10 +1654,14 @@ void silc_server_kill_client(SilcServer server,
     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
 
+    if (remote_client->data.public_key)
+      silc_hash_table_del_by_context(server->pk_hash,
+                                     remote_client->data.public_key,
+                                     remote_client);
+
     if (SILC_IS_LOCAL(remote_client)) {
       server->stat.my_clients--;
       silc_schedule_task_del_by_context(server->schedule, remote_client);
-      silc_idlist_del_data(remote_client);
     }
 
     /* Remove remote client */
@@ -1685,13 +1709,14 @@ silc_server_check_watcher_list_foreach(void *key, void *context,
                                  notify->client,
                                  notify->new_nick ? notify->new_nick :
                                  (const char *)notify->client->nickname,
-                                 notify->notify);
+                                 notify->notify,
+                                 notify->client->data.public_key);
   }
 }
 
-/* This function checks whether the `client' nickname is being watched
-   by someone, and notifies the watcher of the notify change of notify
-   type indicated by `notify'. */
+/* This function checks whether the `client' nickname and/or 'client'
+   public key is being watched by someone, and notifies the watcher of the
+   notify change of notify type indicated by `notify'. */
 
 bool silc_server_check_watcher_list(SilcServer server,
                                    SilcClientEntry client,
@@ -1710,10 +1735,13 @@ bool silc_server_check_watcher_list(SilcServer server,
 
   /* Make hash from the nick, or take it from Client ID */
   if (client->nickname) {
-    char nick[128 + 1];
-    memset(nick, 0, sizeof(nick));
-    silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
-    silc_hash_make(server->md5hash, nick, strlen(nick), hash);
+    unsigned char *nickc;
+    nickc = silc_identifier_check(client->nickname, strlen(client->nickname),
+                                 SILC_STRING_UTF8, 128, NULL);
+    if (!nickc)
+      return FALSE;
+    silc_hash_make(server->md5hash, nickc, strlen(nickc), hash);
+    silc_free(nickc);
   } else {
     memset(hash, 0, sizeof(hash));
     memcpy(hash, client->id->hash, sizeof(client->id->hash));
@@ -1724,10 +1752,17 @@ bool silc_server_check_watcher_list(SilcServer server,
   n.new_nick = new_nick;
   n.notify = notify;
 
-  /* Send notify to all watchers */
+  /* Send notify to all watchers watching this nickname */
   silc_hash_table_find_foreach(server->watcher_list, hash,
                               silc_server_check_watcher_list_foreach, &n);
 
+  /* Send notify to all watchers watching this public key */
+  if (client->data.public_key)
+    silc_hash_table_find_foreach(server->watcher_list_pk,
+                                client->data.public_key,
+                                silc_server_check_watcher_list_foreach,
+                                &n);
+
   return TRUE;
 }
 
@@ -1743,7 +1778,7 @@ bool silc_server_del_from_watcher_list(SilcServer server,
   bool found = FALSE;
 
   silc_hash_table_list(server->watcher_list, &htl);
-  while (silc_hash_table_get(&htl, &key, (void **)&entry)) {
+  while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
     if (entry == client) {
       silc_hash_table_del_by_context(server->watcher_list, key, client);
 
@@ -1761,6 +1796,25 @@ bool silc_server_del_from_watcher_list(SilcServer server,
   }
   silc_hash_table_list_reset(&htl);
 
+  silc_hash_table_list(server->watcher_list_pk, &htl);
+  while (silc_hash_table_get(&htl, &key, (void *)&entry)) {
+    if (entry == client) {
+      silc_hash_table_del_by_context(server->watcher_list_pk, key, client);
+
+      if (client->id)
+       SILC_LOG_DEBUG(("Removing %s from WATCH list",
+                       silc_id_render(client->id, SILC_ID_CLIENT)));
+
+      /* Now check whether there still exists entries with this key, if not
+        then free the key to not leak memory. */
+      if (!silc_hash_table_find(server->watcher_list_pk, key, NULL, NULL))
+        silc_pkcs_public_key_free(key);
+
+      found = TRUE;
+    }
+  }
+  silc_hash_table_list_reset(&htl);
+
   return found;
 }
 
@@ -1830,6 +1884,8 @@ bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
   SilcBuffer entry, idp = NULL, pkp = NULL;
   bool ret = FALSE;
 
+  SILC_LOG_DEBUG(("Matching invite/ban"));
+
   if (type < 1 || type > 3 || !check)
     return FALSE;
 
@@ -1855,7 +1911,7 @@ bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
 
   /* Compare the list */
   silc_hash_table_list(list, &htl);
-  while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
+  while (silc_hash_table_get(&htl, (void *)&t, (void *)&entry)) {
     if (type == t) {
       if (type == 1) {
        if (silc_string_match(entry->data, tmp)) {
@@ -1879,7 +1935,7 @@ bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
 
 /* Process invite or ban information */
 
-void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+bool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
                                   SilcUInt8 action, SilcArgumentPayload args)
 {
   unsigned char *tmp;
@@ -1897,72 +1953,46 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
     tmp = silc_argument_get_first_arg(args, &type, &len);
     while (tmp) {
       if (type == 1) {
-       /* Invite string.  Get the old invite string from hash table
-          and append this at the end of the existing one. */
-       if (!silc_hash_table_find(list, (void *)1, NULL, (void *)&tmp2)) {
-         tmp2 = silc_calloc(1, sizeof(*tmp2));
-         silc_hash_table_add(list, (void *)1, tmp2);
+       /* Check validity of the string */
+       if (!silc_utf8_valid(tmp, len) || !len) {
+         tmp = silc_argument_get_next_arg(args, &type, &len);
+         continue;
        }
 
-       /* Check that the string is not part of invite string already */
-       if (action == 0x00) {
-         if (silc_string_match(tmp2->data, tmp))
+       /* Check if the string is added already */
+       silc_hash_table_list(list, &htl);
+       while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
+         if (type == 1 && silc_string_match(tmp2->data, tmp)) {
+           tmp = NULL;
            break;
-
-         if (len) {
-           if (tmp[len - 1] == ',')
-             tmp[len - 1] = '\0';
-           silc_buffer_strformat(tmp2, tmp, SILC_STR_END);
-           silc_buffer_strformat(tmp2, ",", SILC_STR_END);
-         }
-       } else {
-         /* Announced list.  Check each entry in the list */
-         unsigned char e[256];
-         char *start, *end, *n, *rtmp;
-         int i, k;
-
-         rtmp = silc_memdup(tmp, len);
-         for (i = 0, k = 0; i < len; i++) {
-           if (tmp[i] != ',')
-             continue;
-
-           memset(e, 0, sizeof(e));
-           silc_strncat(e, sizeof(e), tmp + k, i - k);
-           if (!silc_string_match(tmp2->data, e)) {
-             k = i + 1;
-             continue;
-           }
-
-           /* Matches.  Delete it since we have it already */
-           start = strstr(rtmp, e);
-           if (start && strlen(start) >= (i - k)) {
-             end = start + (i - k);
-             n = silc_calloc(strlen(rtmp) - (i - k), sizeof(*n));
-             strncat(n, rtmp, start - rtmp);
-             if (strlen(end) > 1)
-               strncat(n, end + 1, ((rtmp + strlen(rtmp)) - end) - 1);
-             silc_free(rtmp);
-             rtmp = n;
-           }
-
-           k = i + 1;
          }
+       }
+       silc_hash_table_list_reset(&htl);
 
-         /* Save the part that we didn't already have. */
-         if (strlen(rtmp) > 1) {
-           silc_buffer_strformat(tmp2, rtmp, SILC_STR_END);
-           silc_buffer_strformat(tmp2, ",", SILC_STR_END);
-         }
-         silc_free(rtmp);
+       if (tmp) {
+         /* Add the string to hash table */
+         tmp2 = silc_buffer_alloc_size(len + 1);
+         if (tmp[len - 1] == ',')
+           tmp[len - 1] = '\0';
+         silc_buffer_put(tmp2, tmp, len);
+         silc_hash_table_add(list, (void *)1, tmp2);
        }
 
       } else if (type == 2) {
        /* Public key.  Check first if the public key is already on the
           list and ignore it if it is, otherwise, add it to hash table. */
+       SilcPublicKey pk;
+
+       /* Verify validity of the public key */
+       if (!silc_pkcs_public_key_payload_decode(tmp, len, &pk)) {
+         tmp = silc_argument_get_next_arg(args, &type, &len);
+         continue;
+       }
+       silc_pkcs_public_key_free(pk);
 
        /* Check if the public key is in the list already */
        silc_hash_table_list(list, &htl);
-       while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+       while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
          if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
            tmp = NULL;
            break;
@@ -1982,7 +2012,7 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
 
        /* Check if the ID is in the list already */
        silc_hash_table_list(list, &htl);
-       while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+       while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
          if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
            tmp = NULL;
            break;
@@ -2008,36 +2038,36 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
     tmp = silc_argument_get_first_arg(args, &type, &len);
     while (tmp) {
       if (type == 1) {
-       /* Invite string.  Get the old string from hash table and delete
-          the requested string. */
-       char *string = NULL, *start, *end, *n;
-
-       if (silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
-         string = tmp2->head;
-         if (tmp2->truelen && !strncmp(string, tmp, tmp2->truelen - 1)) {
-           /* Delete entire string */
-           silc_hash_table_del(list, (void *)1);
-         } else if (tmp2->truelen) {
-           /* Delete part of the string */
-           start = strstr(string, tmp);
-           if (start && strlen(start) >= len) {
-             end = start + len;
-             n = silc_calloc(strlen(string) - len, sizeof(*n));
-             strncat(n, string, start - string);
-             if (strlen(end) > 1)
-               strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
-             silc_free(tmp2->head);
-             silc_buffer_set(tmp2, n, strlen(n));
-           }
+       /* Check validity of the string */
+       if (!silc_utf8_valid(tmp, len)) {
+         tmp = silc_argument_get_next_arg(args, &type, &len);
+         continue;
+       }
+
+       /* Delete from the list */
+       silc_hash_table_list(list, &htl);
+       while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
+         if (type == 1 && silc_string_match(tmp2->data, tmp)) {
+           silc_hash_table_del_by_context(list, (void *)1, tmp2);
+           break;
          }
        }
+       silc_hash_table_list_reset(&htl);
 
       } else if (type == 2) {
        /* Public key. */
+       SilcPublicKey pk;
+
+       /* Verify validity of the public key */
+       if (!silc_pkcs_public_key_payload_decode(tmp, len, &pk)) {
+         tmp = silc_argument_get_next_arg(args, &type, &len);
+         continue;
+       }
+       silc_pkcs_public_key_free(pk);
 
        /* Delete from the invite list */
        silc_hash_table_list(list, &htl);
-       while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+       while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
          if (type == 2 && !memcmp(tmp2->data, tmp, len)) {
            silc_hash_table_del_by_context(list, (void *)2, tmp2);
            break;
@@ -2050,7 +2080,7 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
 
        /* Delete from the invite list */
        silc_hash_table_list(list, &htl);
-       while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
+       while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) {
          if (type == 3 && !memcmp(tmp2->data, tmp, len)) {
            silc_hash_table_del_by_context(list, (void *)3, tmp2);
            break;
@@ -2062,6 +2092,8 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
       tmp = silc_argument_get_next_arg(args, &type, &len);
     }
   }
+
+  return TRUE;
 }
 
 /* Destructor for invite and ban list entrys */
@@ -2178,7 +2210,7 @@ SilcBuffer silc_server_get_channel_pk_list(SilcServer server,
                     SILC_STR_END);
 
   silc_hash_table_list(channel->channel_pubkeys, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&pk)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&pk)) {
     pkp = silc_pkcs_public_key_payload_encode(pk);
     list = silc_argument_payload_encode_one(list, pkp->data, pkp->len,
                                            announce ? 0x03 :
@@ -2232,7 +2264,7 @@ SilcStatus silc_server_set_channel_pk_list(SilcServer server,
   if (chpk && type == 0x03 && channel->channel_pubkeys &&
       server->server_type != SILC_ROUTER) {
     SilcBuffer sidp;
-    unsigned char mask[4];
+    unsigned char mask[4], ulimit[4];
 
     SILC_LOG_DEBUG(("Router enforces its list, remove old list"));
     silc_hash_table_free(channel->channel_pubkeys);
@@ -2241,8 +2273,10 @@ SilcStatus silc_server_set_channel_pk_list(SilcServer server,
     /* Send notify that removes the old list */
     sidp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
     SILC_PUT32_MSB((channel->mode & (~SILC_CHANNEL_MODE_CHANNEL_AUTH)), mask);
+    if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
+      SILC_PUT32_MSB(channel->user_limit, ulimit);
     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, TRUE,
-                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 7,
+                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 8,
                                       sidp->data, sidp->len,
                                       mask, 4,
                                       channel->cipher,
@@ -2254,7 +2288,13 @@ SilcStatus silc_server_set_channel_pk_list(SilcServer server,
                                       channel->passphrase,
                                       channel->passphrase ?
                                       strlen(channel->passphrase) : 0,
-                                      NULL, 0, NULL, 0);
+                                      NULL, 0, NULL, 0,
+                                      (channel->mode &
+                                       SILC_CHANNEL_MODE_ULIMIT ?
+                                       ulimit : NULL),
+                                      (channel->mode &
+                                       SILC_CHANNEL_MODE_ULIMIT ?
+                                       sizeof(ulimit) : 0));
     silc_buffer_free(sidp);
   }
 
@@ -2305,7 +2345,7 @@ bool silc_server_verify_channel_auth(SilcServer server,
 
   /* Find the public key with the hash */
   if (!silc_hash_table_find(channel->channel_pubkeys, pkhash,
-                           NULL, (void **)&chpk)) {
+                           NULL, (void *)&chpk)) {
     SILC_LOG_DEBUG(("Public key not found in channel public key list"));
     goto out;
   }
index 413bdeb97284c108dec09cb9f6a5b5052b5cd88c..62b3d60fef2527d0c76e14f23fa2d783345e83e9 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -202,7 +202,7 @@ bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
                                 SilcUInt8 type, void *check);
 
 /* Process invite or ban information */
-void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
+bool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
                                   SilcUInt8 action, SilcArgumentPayload args);
 
 /* Destructor for invite or ban list entrys */
index 97fc6cff208a89d2ba5a5ad8a533b934e031b883..f60c15ac1319411c7f26bedcb941ae8f9562d3c1 100644 (file)
@@ -19,6 +19,6 @@
 */
 
 #include "serverincludes.h"
-#include "version_internal.h"
+#include "silcversion.h"
 
 const char *server_version = SILC_DIST_VERSION_STRING;
index 8ff643c1e0f4fc126349a05cdba23d956d3ec844..0afc3f39d67f77aaaf67d490672dc8c5a26c27f1 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -127,9 +127,9 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
     if (auth_data && auth_data_len) {
       if (!silc_utf8_valid(p, strlen(p))) {
        *auth_data_len = silc_utf8_encoded_len(p, strlen(p),
-                                              SILC_STRING_LANGUAGE);
+                                              SILC_STRING_LOCALE);
        *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
-       silc_utf8_encode(p, strlen(p), SILC_STRING_LANGUAGE, *auth_data,
+       silc_utf8_encode(p, strlen(p), SILC_STRING_LOCALE, *auth_data,
                         *auth_data_len);
       } else {
        *auth_data = (void *) strdup(p);
@@ -149,7 +149,7 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
       }
 
     if (*auth_data &&
-       silc_hash_table_find_ext(*auth_data, public_key, (void **)&cached_key,
+       silc_hash_table_find_ext(*auth_data, public_key, (void *)&cached_key,
                                 NULL, silc_hash_public_key, NULL,
                                 silc_hash_public_key_compare, NULL)) {
       silc_pkcs_public_key_free(public_key);
@@ -165,6 +165,8 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, const char *p,
                                           NULL, NULL,
                                           my_free_public_key, NULL,
                                           TRUE);
+      SILC_LOG_DEBUG(("Adding public key '%s' to authentication cache",
+                    public_key->identifier));
       silc_hash_table_add(*auth_data, public_key, public_key);
     }
   } else
@@ -730,7 +732,10 @@ SILC_CONFIG_CALLBACK(fetch_connparam)
     config->tmp = NULL;
     return SILC_CONFIG_OK;
   }
-  SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
+  if (!tmp) {
+    SILC_SERVER_CONFIG_ALLOCTMP(SilcServerConfigConnParams);
+    tmp->reconnect_keep_trying = TRUE;
+  }
 
   if (!strcmp(name, "name")) {
     CONFIG_IS_DOUBLE(tmp->name);
@@ -831,7 +836,7 @@ SILC_CONFIG_CALLBACK(fetch_client)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
+                          (void *)&tmp->passphrase,
                           &tmp->passphrase_len)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
@@ -839,13 +844,13 @@ SILC_CONFIG_CALLBACK(fetch_client)
   }
   else if (!strcmp(name, "publickey")) {
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
   }
   else if (!strcmp(name, "publickeydir")) {
-    if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
+    if (!my_parse_publickeydir((char *) val, (void *)&tmp->publickeys)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
@@ -903,7 +908,7 @@ SILC_CONFIG_CALLBACK(fetch_admin)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
+                          (void *)&tmp->passphrase,
                           &tmp->passphrase_len)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
@@ -911,13 +916,13 @@ SILC_CONFIG_CALLBACK(fetch_admin)
   }
   else if (!strcmp(name, "publickey")) {
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
   }
   else if (!strcmp(name, "publickeydir")) {
-    if (!my_parse_publickeydir((char *) val, (void **)&tmp->publickeys)) {
+    if (!my_parse_publickeydir((char *) val, (void *)&tmp->publickeys)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
@@ -1008,7 +1013,7 @@ SILC_CONFIG_CALLBACK(fetch_server)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
+                          (void *)&tmp->passphrase,
                           &tmp->passphrase_len)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
@@ -1017,7 +1022,7 @@ SILC_CONFIG_CALLBACK(fetch_server)
   else if (!strcmp(name, "publickey")) {
     CONFIG_IS_DOUBLE(tmp->publickeys);
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
@@ -1084,7 +1089,7 @@ SILC_CONFIG_CALLBACK(fetch_router)
   else if (!strcmp(name, "passphrase")) {
     CONFIG_IS_DOUBLE(tmp->passphrase);
     if (!my_parse_authdata(SILC_AUTH_PASSWORD, (char *) val,
-                          (void **)&tmp->passphrase,
+                          (void *)&tmp->passphrase,
                           &tmp->passphrase_len)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
@@ -1093,7 +1098,7 @@ SILC_CONFIG_CALLBACK(fetch_router)
   else if (!strcmp(name, "publickey")) {
     CONFIG_IS_DOUBLE(tmp->publickeys);
     if (!my_parse_authdata(SILC_AUTH_PUBLIC_KEY, (char *) val,
-                          (void **)&tmp->publickeys, NULL)) {
+                          (void *)&tmp->publickeys, NULL)) {
       got_errno = SILC_CONFIG_EPRINTLINE;
       goto got_err;
     }
@@ -1258,11 +1263,11 @@ static const SilcConfigTable table_connparam[] = {
   { "version_software",               SILC_CONFIG_ARG_STR,    fetch_connparam, NULL },
   { "version_software_vendor", SILC_CONFIG_ARG_STR,    fetch_connparam,        NULL },
   { "anonymous",               SILC_CONFIG_ARG_TOGGLE, fetch_connparam,        NULL },
-  { "qos",                    SILC_CONFIG_ARG_TOGGLE,  fetch_generic,  NULL },
-  { "qos_rate_limit",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
-  { "qos_bytes_limit",         SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
-  { "qos_limit_sec",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
-  { "qos_limit_usec",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "qos",                    SILC_CONFIG_ARG_TOGGLE, fetch_connparam, NULL },
+  { "qos_rate_limit",          SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
+  { "qos_bytes_limit",         SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
+  { "qos_limit_sec",           SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
+  { "qos_limit_usec",          SILC_CONFIG_ARG_INT,    fetch_connparam,        NULL },
   { 0, 0, 0, 0 }
 };
 
@@ -1373,6 +1378,7 @@ static bool silc_server_config_check(SilcServerConfig config)
         "connection. You have marked it incorrectly as backup router."));
     ret = FALSE;
   }
+#if 0
   if (config->routers && config->routers->initiator == FALSE &&
       config->routers->backup_router == FALSE) {
     SILC_SERVER_LOG_ERROR((
@@ -1380,6 +1386,7 @@ static bool silc_server_config_check(SilcServerConfig config)
         "connection and it must be marked as Initiator."));
     ret = FALSE;
   }
+#endif
   if (config->routers && config->routers->backup_router == TRUE &&
       !config->servers && !config->routers->next) {
     SILC_SERVER_LOG_ERROR((
@@ -1399,10 +1406,16 @@ static bool silc_server_config_check(SilcServerConfig config)
          "same host.", r->host));
       ret = FALSE;
     }
+
+    if (r->initiator == FALSE && r->port != 0) {
+      SILC_SERVER_LOG_WARNING(("\nWarning: Initiator is FALSE and Port is "
+                               "specified. Ignoring Port value."));
+      r->port = 0;
+    }
   }
-  
+
   /* ServerConnection sanity checks */
-  
+
   for (s = config->servers; s; s = s->next) {
     if (s->backup_router) {
       b = TRUE;
@@ -1446,6 +1459,7 @@ SilcServerConfig silc_server_config_alloc(const char *filename)
   /* general config defaults */
   config_new->refcount = 1;
   config_new->logging_timestamp = TRUE;
+  config_new->param.reconnect_keep_trying = TRUE;
 
   /* obtain a config file object */
   file = silc_config_open(filename);
index 7d8fdea5c1f059e28cf8ffd9d779677c8d2c75f4..3d4ea8e0970aedbde57203aa4ef8ab332ea2e64c 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -56,21 +56,20 @@ void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
 
 bool silc_id_create_client_id(SilcServer server,
                              SilcServerID *server_id, SilcRng rng,
-                             SilcHash md5hash, char *nickname, 
+                             SilcHash md5hash,
+                             unsigned char *nickname, SilcUInt32 nick_len,
                              SilcClientID **new_id)
 {
   unsigned char hash[16];
   bool finding = FALSE;
-  char nick[128 + 1];
 
   SILC_LOG_DEBUG(("Creating new Client ID"));
 
   *new_id = silc_calloc(1, sizeof(**new_id));
 
-  /* Create hash of the nickanem */
-  memset(nick, 0, sizeof(nick));
-  silc_to_lower(nickname, nick, sizeof(nick) - 1);
-  silc_hash_make(md5hash, nick, strlen(nick), hash);
+  /* Create hash of the nickname (it's already checked as valid identifier
+     string). */
+  silc_hash_make(md5hash, nickname, nick_len, hash);
 
   /* Create the ID */
   memcpy((*new_id)->ip.data, server_id->ip.data, server_id->ip.data_len);
@@ -80,9 +79,9 @@ bool silc_id_create_client_id(SilcServer server,
 
   /* Assure that the ID does not exist already */
   while (1) {
-    if (!silc_idlist_find_client_by_id(server->local_list, 
+    if (!silc_idlist_find_client_by_id(server->local_list,
                                       *new_id, FALSE, NULL))
-      if (!silc_idlist_find_client_by_id(server->global_list, 
+      if (!silc_idlist_find_client_by_id(server->global_list,
                                         *new_id, FALSE, NULL))
        break;
 
@@ -126,15 +125,15 @@ bool silc_id_create_channel_id(SilcServer server,
 
   /* Assure that the ID does not exist already */
   while (1) {
-    if (!silc_idlist_find_channel_by_id(server->local_list, 
+    if (!silc_idlist_find_channel_by_id(server->local_list,
                                        *new_id, NULL))
       break;
 
     (*new_id)->rnd++;
-    
+
     if (finding && (*new_id)->rnd == 0)
       return FALSE;
-    
+
     if (!finding) {
       (*new_id)->rnd = 0;
       finding = TRUE;
index ce70e7af94c33d29aedd39cd52247c1ba232f1de..4f81aa17ad0421658036e59e0b044abccdbe2983 100644 (file)
@@ -4,13 +4,13 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, 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
 #define SERVERID_H
 
 /* Prototypes */
-void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng, 
+void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
                              SilcServerID **new_id);
 bool silc_id_create_client_id(SilcServer server,
                              SilcServerID *server_id, SilcRng rng,
-                             SilcHash md5hash, char *nickname, 
+                             SilcHash md5hash, unsigned char *nickname,
+                             SilcUInt32 nick_len,
                              SilcClientID **new_id);
 bool silc_id_create_channel_id(SilcServer server,
                               SilcServerID *router_id, SilcRng rng,
index 9e2c2a16b0ee5b161d4ad675fd13d5f41f3933b4..86d75b553536e0c8aa2cfe215003ec570ac1bfd5 100644 (file)
@@ -302,6 +302,7 @@ SILC_TASK_CALLBACK(dump_stats)
   STAT_OUTPUT("  Authentication failures : %d", silcd->stat.auth_failures);
   STAT_OUTPUT("  Packets sent            : %d", silcd->stat.packets_sent);
   STAT_OUTPUT("  Packets received        : %d", silcd->stat.packets_received);
+  STAT_OUTPUT("  Connections             : %d", silcd->stat.conn_num);
 
 #undef STAT_OUTPUT
 
@@ -315,6 +316,7 @@ SILC_TASK_CALLBACK(dump_stats)
   fprintf(fdd, "  backup_router          : %d\n", silcd->backup_router);
   fprintf(fdd, "  backup_primary         : %d\n", silcd->backup_primary);
   fprintf(fdd, "  backup_noswitch        : %d\n", silcd->backup_noswitch);
+  fprintf(fdd, "  backup_closed          : %d\n", silcd->backup_closed);
   fprintf(fdd, "  wait_backup            : %d\n", silcd->wait_backup);
   if (silcd->router)
     fprintf(fdd, "  primary router         : %s\n",
@@ -390,11 +392,14 @@ SILC_TASK_CALLBACK(dump_stats)
        c = 1;
        while (id_cache) {
          client_entry = (SilcClientEntry)id_cache->context;
-         fprintf(fdd, "  %d: name %s id %s status 0x%x\n", c,
+         server_entry = client_entry->router;
+         fprintf(fdd, "  %d: name %s id %s status 0x%x from %s\n", c,
                  client_entry->nickname ? client_entry->nickname :
                  (unsigned char *)"N/A", client_entry->id ?
                  silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
-                 client_entry->data.status);
+                 client_entry->data.status, server_entry ?
+                 server_entry->server_name ? server_entry->server_name : 
+                 "N/A" : "local");
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          c++;
@@ -408,11 +413,14 @@ SILC_TASK_CALLBACK(dump_stats)
        c = 1;
        while (id_cache) {
          client_entry = (SilcClientEntry)id_cache->context;
-         fprintf(fdd, "  %d: name %s id %s status 0x%x\n", c,
+         server_entry = client_entry->router;
+         fprintf(fdd, "  %d: name %s id %s status 0x%x from %s\n", c,
                  client_entry->nickname ? client_entry->nickname :
                  (unsigned char *)"N/A", client_entry->id ?
                  silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
-                 client_entry->data.status);
+                 client_entry->data.status, server_entry ?
+                 server_entry->server_name ? server_entry->server_name : 
+                 "N/A" : "local");
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          c++;
@@ -461,6 +469,8 @@ SILC_TASK_CALLBACK(dump_stats)
   fclose(fdd);
 }
 
+#ifdef SILC_DEBUG
+
 typedef struct {
   int level;
   const char *string;
@@ -540,6 +550,7 @@ static void silc_get_debug_level(int level)
       break;
     }
 }
+#endif /* SILC_DEBUG */
 
 /* This function should not be called directly but through the appropriate
    wrapper macro defined in server.h */
@@ -588,7 +599,7 @@ int main(int argc, char **argv)
          printf("SILCd Secure Internet Live Conferencing daemon, "
                 "version %s (base: SILC Toolkit %s)\n",
                 silc_dist_version, silc_version);
-         printf("(c) 1997 - 2002 Pekka Riikonen "
+         printf("(c) 1997 - 2005 Pekka Riikonen "
                 "<priikone@silcnet.org>\n");
          exit(0);
          break;
index f1657bbc46471af91d3bd85a01b289b939ae851b..6641456623484695a632468c7a9bd0dc700b8656 100755 (executable)
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
-timestamp='2002-09-03'
+timestamp='2004-07-19'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -98,30 +98,32 @@ trap 'exit 1' 1 2 15
 # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
 # use `HOST_CC' if defined, but it is deprecated.
 
-# This shell variable is my proudest work .. or something. --bje
+# Portable tmp directory creation inspired by the Autoconf team.
 
-set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ;
-(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old)
-   || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ;
-dummy=$tmpdir/dummy ;
-files="$dummy.c $dummy.o $dummy.rel $dummy" ;
-trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ;
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
 case $CC_FOR_BUILD,$HOST_CC,$CC in
  ,,)    echo "int x;" > $dummy.c ;
        for c in cc gcc c89 c99 ; do
-         if ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; then
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
             CC_FOR_BUILD="$c"; break ;
          fi ;
        done ;
-       rm -f $files ;
        if test x"$CC_FOR_BUILD" = x ; then
          CC_FOR_BUILD=no_compiler_found ;
        fi
        ;;
  ,,*)   CC_FOR_BUILD=$CC ;;
  ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-esac ;
-unset files'
+esac ;'
 
 # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
 # (ghazi@noc.rutgers.edu 1994-08-24)
@@ -178,21 +180,41 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
                ;;
        esac
        # The OS release
-       release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
        # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
        # contains redundant information, the shorter form:
        # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
        echo "${machine}-${os}${release}"
        exit 0 ;;
+    amd64:OpenBSD:*:*)
+       echo x86_64-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
     amiga:OpenBSD:*:*)
        echo m68k-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
     arc:OpenBSD:*:*)
        echo mipsel-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
+    cats:OpenBSD:*:*)
+       echo arm-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
     hp300:OpenBSD:*:*)
        echo m68k-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
+    luna88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
     mac68k:OpenBSD:*:*)
        echo m68k-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
@@ -223,71 +245,67 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:OpenBSD:*:*)
        echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
        exit 0 ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:MirBSD:*:*)
+       echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit 0 ;;
     alpha:OSF1:*:*)
-       if test $UNAME_RELEASE = "V4.0"; then
+       case $UNAME_RELEASE in
+       *4.0)
                UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-       fi
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
        # A Vn.n version is a released version.
        # A Tn.n version is a released field test version.
        # A Xn.n version is an unreleased experimental baselevel.
        # 1.2 uses "1.2" for uname -r.
-       eval $set_cc_for_build
-       cat <<EOF >$dummy.s
-       .data
-\$Lformat:
-       .byte 37,100,45,37,120,10,0     # "%d-%x\n"
-
-       .text
-       .globl main
-       .align 4
-       .ent main
-main:
-       .frame \$30,16,\$26,0
-       ldgp \$29,0(\$27)
-       .prologue 1
-       .long 0x47e03d80 # implver \$0
-       lda \$2,-1
-       .long 0x47e20c21 # amask \$2,\$1
-       lda \$16,\$Lformat
-       mov \$0,\$17
-       not \$1,\$18
-       jsr \$26,printf
-       ldgp \$29,0(\$26)
-       mov 0,\$16
-       jsr \$26,exit
-       .end main
-EOF
-       $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
-       if test "$?" = 0 ; then
-               case `$dummy` in
-                       0-0)
-                               UNAME_MACHINE="alpha"
-                               ;;
-                       1-0)
-                               UNAME_MACHINE="alphaev5"
-                               ;;
-                       1-1)
-                               UNAME_MACHINE="alphaev56"
-                               ;;
-                       1-101)
-                               UNAME_MACHINE="alphapca56"
-                               ;;
-                       2-303)
-                               UNAME_MACHINE="alphaev6"
-                               ;;
-                       2-307)
-                               UNAME_MACHINE="alphaev67"
-                               ;;
-                       2-1307)
-                               UNAME_MACHINE="alphaev68"
-                               ;;
-                       3-1307)
-                               UNAME_MACHINE="alphaev7"
-                               ;;
-               esac
-       fi
-       rm -f $dummy.s $dummy && rmdir $tmpdir
-       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
        exit 0 ;;
     Alpha\ *:Windows_NT*:*)
        # How do we know it's Interix rather than the generic POSIX subsystem?
@@ -310,6 +328,9 @@ EOF
     *:OS/390:*:*)
        echo i370-ibm-openedition
        exit 0 ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit 0 ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
        echo arm-acorn-riscix${UNAME_RELEASE}
        exit 0;;
@@ -327,6 +348,9 @@ EOF
     NILE*:*:*:dcosx)
        echo pyramid-pyramid-svr4
        exit 0 ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit 0 ;;
     DRS?6000:UNIX_SV:4.2*:7*)
        case `/usr/bin/uname -p` in
            sparc) echo sparc-icl-nx7 && exit 0 ;;
@@ -399,6 +423,9 @@ EOF
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
         echo m68k-unknown-mint${UNAME_RELEASE}
         exit 0 ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
     powerpc:machten:*:*)
        echo powerpc-apple-machten${UNAME_RELEASE}
        exit 0 ;;
@@ -437,10 +464,9 @@ EOF
          exit (-1);
        }
 EOF
-       $CC_FOR_BUILD $dummy.c -o $dummy \
+       $CC_FOR_BUILD -o $dummy $dummy.c \
          && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
-         && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-       rm -f $dummy.c $dummy && rmdir $tmpdir
+         && exit 0
        echo mips-mips-riscos${UNAME_RELEASE}
        exit 0 ;;
     Motorola:PowerMAX_OS:*:*)
@@ -449,7 +475,7 @@ EOF
     Motorola:*:4.3:PL8-*)
        echo powerpc-harris-powermax
        exit 0 ;;
-    Night_Hawk:*:*:PowerMAX_OS)
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
        echo powerpc-harris-powermax
        exit 0 ;;
     Night_Hawk:Power_UNIX:*:*)
@@ -524,8 +550,7 @@ EOF
                        exit(0);
                        }
 EOF
-               $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-               rm -f $dummy.c $dummy && rmdir $tmpdir
+               $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
                echo rs6000-ibm-aix3.2.5
        elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
                echo rs6000-ibm-aix3.2.4
@@ -623,11 +648,21 @@ EOF
                   exit (0);
               }
 EOF
-                   (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`$dummy`
-                   if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
-                   rm -f $dummy.c $dummy && rmdir $tmpdir
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
                fi ;;
        esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           # avoid double evaluation of $set_cc_for_build
+           test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
        echo ${HP_ARCH}-hp-hpux${HPUX_REV}
        exit 0 ;;
     ia64:HP-UX:*:*)
@@ -661,8 +696,7 @@ EOF
          exit (0);
        }
 EOF
-       $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-       rm -f $dummy.c $dummy && rmdir $tmpdir
+       $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
        echo unknown-hitachi-hiuxwe2
        exit 0 ;;
     9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
@@ -720,21 +754,26 @@ EOF
     CRAY*TS:*:*:*)
        echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
-    CRAY*T3D:*:*:*)
-       echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit 0 ;;
     CRAY*T3E:*:*:*)
        echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
     CRAY*SV1:*:*:*)
        echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
        exit 0 ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
        FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
         FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
         FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
         echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
         exit 0 ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit 0 ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
        echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
        exit 0 ;;
@@ -745,19 +784,7 @@ EOF
        echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
        exit 0 ;;
     *:FreeBSD:*:*)
-       # Determine whether the default compiler uses glibc.
-       eval $set_cc_for_build
-       sed 's/^        //' << EOF >$dummy.c
-       #include <features.h>
-       #if __GLIBC__ >= 2
-       LIBC=gnu
-       #else
-       LIBC=
-       #endif
-EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-       rm -f $dummy.c && rmdir $tmpdir
-       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
        exit 0 ;;
     i*:CYGWIN*:*)
        echo ${UNAME_MACHINE}-pc-cygwin
@@ -768,14 +795,17 @@ EOF
     i*:PW*:*)
        echo ${UNAME_MACHINE}-pc-pw32
        exit 0 ;;
-    x86:Interix*:3*)
-       echo i386-pc-interix3
+    x86:Interix*:[34]*)
+       echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+       exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
        exit 0 ;;
     i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
        # How do we know it's Interix rather than the generic POSIX subsystem?
        # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
        # UNAME_MACHINE based on the output of uname instead of i386?
-       echo i386-pc-interix
+       echo i586-pc-interix
        exit 0 ;;
     i*:UWIN*:*)
        echo ${UNAME_MACHINE}-pc-uwin
@@ -787,17 +817,28 @@ EOF
        echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
        exit 0 ;;
     *:GNU:*:*)
+       # the GNU system
        echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
        exit 0 ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit 0 ;;
     i*86:Minix:*:*)
        echo ${UNAME_MACHINE}-pc-minix
        exit 0 ;;
     arm*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
        exit 0 ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit 0 ;;
     ia64:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
        exit 0 ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
     m68*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
        exit 0 ;;
@@ -818,8 +859,26 @@ EOF
        #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
-       rm -f $dummy.c && rmdir $tmpdir
-       test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+       ;;
+    mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef mips64
+       #undef mips64el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=mips64el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=mips64
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
        ;;
     ppc:Linux:*:*)
        echo powerpc-unknown-linux-gnu
@@ -855,6 +914,9 @@ EOF
     s390:Linux:*:* | s390x:Linux:*:*)
        echo ${UNAME_MACHINE}-ibm-linux
        exit 0 ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
     sh*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
        exit 0 ;;
@@ -912,9 +974,11 @@ EOF
        LIBC=gnuaout
        #endif
        #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-       rm -f $dummy.c && rmdir $tmpdir
        test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
        test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
        ;;
@@ -932,6 +996,26 @@ EOF
         # Use sysv4.2uw... so that sysv4* matches it.
        echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
        exit 0 ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit 0 ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit 0 ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit 0 ;;
+       i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit 0 ;;
     i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
        UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
        if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
@@ -966,9 +1050,6 @@ EOF
                echo ${UNAME_MACHINE}-pc-sysv32
        fi
        exit 0 ;;
-    i*86:*DOS:*:*)
-       echo ${UNAME_MACHINE}-pc-msdosdjgpp
-       exit 0 ;;
     pc:*:*:*)
        # Left here for compatibility:
         # uname -m prints for DJGPP always 'pc', but it prints nothing about
@@ -995,9 +1076,12 @@ EOF
     mc68k:UNIX:SYSTEM5:3.51m)
        echo m68k-convergent-sysv
        exit 0 ;;
-    M68*:*:R3V[567]*:*)
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit 0 ;;
+    M68*:*:R3V[5678]*:*)
        test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
-    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
        OS_REL=''
        test -r /etc/.relid \
        && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
@@ -1014,9 +1098,6 @@ EOF
     mc68030:UNIX_System_V:4.*:*)
        echo m68k-atari-sysv4
        exit 0 ;;
-    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
-       echo i386-unknown-lynxos${UNAME_RELEASE}
-       exit 0 ;;
     TSUNAMI:LynxOS:2.*:*)
        echo sparc-unknown-lynxos${UNAME_RELEASE}
        exit 0 ;;
@@ -1098,7 +1179,11 @@ EOF
        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
        exit 0 ;;
     *:Darwin:*:*)
-       echo `uname -p`-apple-darwin${UNAME_RELEASE}
+       case `uname -p` in
+           *86) UNAME_PROCESSOR=i686 ;;
+           powerpc) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
        exit 0 ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
        UNAME_PROCESSOR=`uname -p`
@@ -1111,7 +1196,7 @@ EOF
     *:QNX:*:4*)
        echo i386-pc-qnx
        exit 0 ;;
-    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+    NSR-?:NONSTOP_KERNEL:*:*)
        echo nsr-tandem-nsk${UNAME_RELEASE}
        exit 0 ;;
     *:NonStop-UX:*:*)
@@ -1134,11 +1219,6 @@ EOF
        fi
        echo ${UNAME_MACHINE}-unknown-plan9
        exit 0 ;;
-    i*86:OS/2:*:*)
-       # If we were able to find `uname', then EMX Unix compatibility
-       # is probably installed.
-       echo ${UNAME_MACHINE}-pc-os2-emx
-       exit 0 ;;
     *:TOPS-10:*:*)
        echo pdp10-unknown-tops10
        exit 0 ;;
@@ -1157,12 +1237,19 @@ EOF
     *:ITS:*:*)
        echo pdp10-unknown-its
        exit 0 ;;
-    i*86:XTS-300:*:STOP)
-       echo ${UNAME_MACHINE}-unknown-stop
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
        exit 0 ;;
-    i*86:atheos:*:*)
-       echo ${UNAME_MACHINE}-unknown-atheos
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
        exit 0 ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms && exit 0 ;;
+           I*) echo ia64-dec-vms && exit 0 ;;
+           V*) echo vax-dec-vms && exit 0 ;;
+       esac
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1283,8 +1370,7 @@ main ()
 }
 EOF
 
-$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0
-rm -f $dummy.c $dummy && rmdir $tmpdir
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
 
 # Apollos put the system type in the environment.
 
index 1dea9b79d5500e4e629a7f841d4a969d7b8412c6..ac6de9869c9a1b0a8145abac6ac35d9854fb11f9 100755 (executable)
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
-timestamp='2002-09-05'
+timestamp='2004-06-24'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -70,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -118,7 +118,8 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
+  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
@@ -144,7 +145,7 @@ case $os in
        -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
        -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
        -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-       -apple | -axis)
+       -apple | -axis | -knuth | -cray)
                os=
                basic_machine=$1
                ;;
@@ -228,14 +229,15 @@ case $basic_machine in
        | a29k \
        | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
        | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
        | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
-       | clipper \
+       | c4x | clipper \
        | d10v | d30v | dlx | dsp16xx \
        | fr30 | frv \
        | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
        | i370 | i860 | i960 | ia64 \
-       | ip2k \
-       | m32r | m68000 | m68k | m88k | mcore \
+       | ip2k | iq2000 \
+       | m32r | m32rle | m68000 | m68k | m88k | mcore \
        | mips | mipsbe | mipseb | mipsel | mipsle \
        | mips16 \
        | mips64 | mips64el \
@@ -245,21 +247,24 @@ case $basic_machine in
        | mips64vr4300 | mips64vr4300el \
        | mips64vr5000 | mips64vr5000el \
        | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
        | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
        | mipsisa64sb1 | mipsisa64sb1el \
        | mipsisa64sr71k | mipsisa64sr71kel \
        | mipstx39 | mipstx39el \
        | mn10200 | mn10300 \
+       | msp430 \
        | ns16k | ns32k \
        | openrisc | or32 \
        | pdp10 | pdp11 | pj | pjl \
        | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
        | pyramid \
-       | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+       | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
        | sh64 | sh64le \
-       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
        | strongarm \
-       | tahoe | thumb | tic80 | tron \
+       | tahoe | thumb | tic4x | tic80 | tron \
        | v850 | v850e \
        | we32k \
        | x86 | xscale | xstormy16 | xtensa \
@@ -294,16 +299,16 @@ case $basic_machine in
        | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
        | avr-* \
        | bs2000-* \
-       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \
-       | clipper-* | cydra-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | craynv-* | cydra-* \
        | d10v-* | d30v-* | dlx-* \
        | elxsi-* \
        | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
        | h8300-* | h8500-* \
        | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
        | i*86-* | i860-* | i960-* | ia64-* \
-       | ip2k-* \
-       | m32r-* \
+       | ip2k-* | iq2000-* \
+       | m32r-* | m32rle-* \
        | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
        | m88110-* | m88k-* | mcore-* \
        | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
@@ -315,21 +320,27 @@ case $basic_machine in
        | mips64vr4300-* | mips64vr4300el-* \
        | mips64vr5000-* | mips64vr5000el-* \
        | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
        | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
        | mipsisa64sb1-* | mipsisa64sb1el-* \
        | mipsisa64sr71k-* | mipsisa64sr71kel-* \
-       | mipstx39 | mipstx39el \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | msp430-* \
        | none-* | np1-* | ns16k-* | ns32k-* \
        | orion-* \
        | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
        | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
        | pyramid-* \
        | romp-* | rs6000-* \
-       | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \
+       | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
        | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
        | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
-       | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
-       | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+       | tron-* \
        | v850-* | v850e-* | vax-* \
        | we32k-* \
        | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
@@ -353,6 +364,9 @@ case $basic_machine in
                basic_machine=a29k-amd
                os=-udi
                ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
        adobe68k)
                basic_machine=m68010-adobe
                os=-scout
@@ -367,6 +381,12 @@ case $basic_machine in
                basic_machine=a29k-none
                os=-bsd
                ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
        amdahl)
                basic_machine=580-amdahl
                os=-sysv
@@ -426,12 +446,24 @@ case $basic_machine in
                basic_machine=j90-cray
                os=-unicos
                ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16c)
+               basic_machine=cr16c-unknown
+               os=-elf
+               ;;
        crds | unos)
                basic_machine=m68k-crds
                ;;
        cris | cris-* | etrax*)
                basic_machine=cris-axis
                ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
        da30 | da30-*)
                basic_machine=m68k-da30
                ;;
@@ -632,10 +664,6 @@ case $basic_machine in
        mips3*)
                basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
                ;;
-       mmix*)
-               basic_machine=mmix-knuth
-               os=-mmixware
-               ;;
        monitor)
                basic_machine=m68k-rom68k
                os=-coff
@@ -727,6 +755,10 @@ case $basic_machine in
                basic_machine=or32-unknown
                os=-coff
                ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
        OSE68000 | ose68000)
                basic_machine=m68000-ericsson
                os=-ose
@@ -758,18 +790,24 @@ case $basic_machine in
        pentiumpro | p6 | 6x86 | athlon | athlon_*)
                basic_machine=i686-pc
                ;;
-       pentiumii | pentium2)
+       pentiumii | pentium2 | pentiumiii | pentium3)
                basic_machine=i686-pc
                ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
        pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
                basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
        pentiumpro-* | p6-* | 6x86-* | athlon-*)
                basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
-       pentiumii-* | pentium2-*)
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
                basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
                ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
        pn)
                basic_machine=pn-gould
                ;;
@@ -828,6 +866,10 @@ case $basic_machine in
        sb1el)
                basic_machine=mipsisa64sb1el-unknown
                ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
        sequent)
                basic_machine=i386-sequent
                ;;
@@ -835,6 +877,9 @@ case $basic_machine in
                basic_machine=sh-hitachi
                os=-hms
                ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
        sparclite-wrs | simso-wrs)
                basic_machine=sparclite-wrs
                os=-vxworks
@@ -901,10 +946,6 @@ case $basic_machine in
                basic_machine=i386-sequent
                os=-dynix
                ;;
-       t3d)
-               basic_machine=alpha-cray
-               os=-unicos
-               ;;
        t3e)
                basic_machine=alphaev5-cray
                os=-unicos
@@ -913,14 +954,18 @@ case $basic_machine in
                basic_machine=t90-cray
                os=-unicos
                ;;
-        tic4x | c4x*)
-               basic_machine=tic4x-unknown
-               os=-coff
-               ;;
        tic54x | c54x*)
                basic_machine=tic54x-unknown
                os=-coff
                ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
        tx39)
                basic_machine=mipstx39-unknown
                ;;
@@ -934,6 +979,10 @@ case $basic_machine in
        tower | tower-32)
                basic_machine=m68k-ncr
                ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
        udi29k)
                basic_machine=a29k-amd
                os=-udi
@@ -977,10 +1026,6 @@ case $basic_machine in
                basic_machine=hppa1.1-winbond
                os=-proelf
                ;;
-       windows32)
-               basic_machine=i386-pc
-               os=-windows32-msvcrt
-               ;;
        xps | xps100)
                basic_machine=xps100-honeywell
                ;;
@@ -1011,6 +1056,9 @@ case $basic_machine in
        romp)
                basic_machine=romp-ibm
                ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
        rs6000)
                basic_machine=rs6000-ibm
                ;;
@@ -1027,13 +1075,13 @@ case $basic_machine in
        we32k)
                basic_machine=we32k-att
                ;;
-       sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele)
+       sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
                basic_machine=sh-unknown
                ;;
        sh64)
                basic_machine=sh64-unknown
                ;;
-       sparc | sparcv9 | sparcv9b)
+       sparc | sparcv8 | sparcv9 | sparcv9b)
                basic_machine=sparc-sun
                ;;
        cydra)
@@ -1106,18 +1154,20 @@ case $os in
              | -aos* \
              | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
              | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
-             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
              | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
              | -chorusos* | -chorusrdb* \
              | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-             | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
-             | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+             | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
              | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
              | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
              | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
-             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*)
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*)
        # Remember, each alternative MUST END IN *, to match a version number.
                ;;
        -qnx*)
@@ -1129,8 +1179,10 @@ case $os in
                        ;;
                esac
                ;;
+       -nto-qnx*)
+               ;;
        -nto*)
-               os=-nto-qnx
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
                ;;
        -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
              | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
@@ -1139,6 +1191,9 @@ case $os in
        -mac*)
                os=`echo $os | sed -e 's|mac|macos|'`
                ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
        -linux*)
                os=`echo $os | sed -e 's|linux|linux-gnu|'`
                ;;
@@ -1151,6 +1206,9 @@ case $os in
        -opened*)
                os=-openedition
                ;;
+        -os400*)
+               os=-os400
+               ;;
        -wince*)
                os=-wince
                ;;
@@ -1172,6 +1230,9 @@ case $os in
        -atheos*)
                os=-atheos
                ;;
+       -syllable*)
+               os=-syllable
+               ;;
        -386bsd)
                os=-bsd
                ;;
@@ -1194,6 +1255,9 @@ case $os in
        -sinix*)
                os=-sysv4
                ;;
+        -tpf*)
+               os=-tpf
+               ;;
        -triton*)
                os=-sysv3
                ;;
@@ -1224,6 +1288,12 @@ case $os in
        -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
                os=-mint
                ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
        -none)
                ;;
        *)
@@ -1255,6 +1325,9 @@ case $basic_machine in
        arm*-semi)
                os=-aout
                ;;
+    c4x-* | tic4x-*)
+        os=-coff
+        ;;
        # This must come before the *-dec entry.
        pdp10-*)
                os=-tops20
@@ -1301,6 +1374,9 @@ case $basic_machine in
        *-ibm)
                os=-aix
                ;;
+       *-knuth)
+               os=-mmixware
+               ;;
        *-wec)
                os=-proelf
                ;;
@@ -1433,9 +1509,15 @@ case $basic_machine in
                        -mvs* | -opened*)
                                vendor=ibm
                                ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
                        -ptx*)
                                vendor=sequent
                                ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
                        -vxsim* | -vxworks* | -windiss*)
                                vendor=wrs
                                ;;
similarity index 78%
rename from configure.in.pre
rename to configure.ad
index c8230507246b051b77b65d5e76b4fbb64be71852..410d19f23c4205d405c4eba874ac7a3c1693220e 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  configure.in.pre
+#  configure.ad
 #
 #  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 - 2002 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
 #  GNU General Public License for more details.
 #
 
-AC_INIT(includes/silcversion.h)
+AD_INIT
+AC_CANONICAL_SYSTEM
+AM_INIT_AUTOMAKE
+AC_PREREQ(2.52)
+AC_CONFIG_HEADERS(silcdefs.h)
+
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
 
+AC_PROG_LN_S
+AC_SUBST(LN_S)
+AC_PATH_PROG(sedpath, sed)
+
+#ifdef SILC_DIST_COMPILER
 # Put here any platform specific stuff
 #
-AC_CANONICAL_SYSTEM
 case "$target" in
   *-*-freebsd*)
     check_threads=true
@@ -33,79 +43,18 @@ case "$target" in
     ;;
 esac
 
-# ./prepare script will automatically put the correct version. Do not edit!
-#
-AM_INIT_AUTOMAKE(SILC_PACKAGE, SILC_VERSION)
-AC_PREREQ(2.52)
-AC_CONFIG_HEADERS(includes/silcdefs.h)
-
 CFLAGS=
 AC_PROG_CC
 AC_C_INLINE
 AC_C_CONST
 
-AC_PROG_LN_S
-AC_SUBST(LN_S)
-
-##
-## Distribution definition. ./prepare will automatically add here a correct
-## value. Do not edit!
-##
-silc_dist=SILC_PACKAGE
-SILC_DIST_SUBDIRS="SILC_DISTRIBUTION_SUBDIRS"
-AC_DEFINE(SILC_DIST_DEFINE)
-
-
-##
-## Library versioning.
-##
-# Do the releases and library versioning according to following rules:
-#
-#  - If any code has changed in library, increment [LIB]_REVISION
-#  - If functions were added, set [LIB]_REVISION to 0
-#  - If functions were added, removed or changed, increment [LIB]_CURRENT
-#  - If functions were added, increment [LIB]_AGE
-#  - If functions were removed, set [LIB]_AGE to 0
-#
-# where [LIB] is LIBSILC and LIBSILCCLIENT, and where "functions" means
-# functions public interfaces.
-#
-# The LIB_BASE_VERSION defines the SILC software major.minor version and 
-# it is increment only when these version numbers actually change.
-#
-
-# Base version for libraries.  Do not change this unless SILC version
-# changes too.
-LIB_BASE_VERSION=1.0
-
-# libsilc versions
-LIBSILC_CURRENT=2
-LIBSILC_REVISION=0
-LIBSILC_AGE=0
-
-# libsilcclient versions
-LIBSILCCLIENT_CURRENT=2
-LIBSILCCLIENT_REVISION=0
-LIBSILCCLIENT_AGE=0
-
-# Substitute the version numbers
-AC_SUBST(LIB_BASE_VERSION)
-AC_SUBST(LIBSILC_CURRENT)
-AC_SUBST(LIBSILC_REVISION)
-AC_SUBST(LIBSILC_AGE)
-AC_SUBST(LIBSILCCLIENT_CURRENT)
-AC_SUBST(LIBSILCCLIENT_REVISION)
-AC_SUBST(LIBSILCCLIENT_AGE)
+__SILC_HAVE_PTHREAD=""
+__SILC_HAVE_SIM=""
+__SILC_ENABLE_DEBUG=""
 
-#
-# Program checking
-#
-AC_PROG_INSTALL
 AC_PROG_RANLIB
-AC_PROG_MAKE_SET
 AC_DISABLE_SHARED
 AC_PROG_LIBTOOL
-AC_PATH_PROG(sedpath, sed)
 
 # Header checking
 #
@@ -117,7 +66,7 @@ AC_HEADER_STAT
 #
 AC_CHECK_HEADERS(unistd.h string.h getopt.h errno.h fcntl.h assert.h)
 AC_CHECK_HEADERS(sys/types.h sys/stat.h sys/time.h stddef.h)
-AC_CHECK_HEADERS(netinet/in.h netinet/tcp.h xti.h netdb.h)
+AC_CHECK_HEADERS(netinet/in.h netinet/tcp.h xti.h netdb.h sys/resource.h)
 AC_CHECK_HEADERS(pwd.h grp.h termcap.h paths.h)
 AC_CHECK_HEADERS(ncurses.h signal.h ctype.h utime.h)
 AC_CHECK_HEADERS(arpa/inet.h sys/mman.h limits.h termios.h locale.h langinfo.h)
@@ -157,12 +106,13 @@ AC_CHECK_FUNC(socket, [],
 )
 AC_CHECK_FUNCS(gethostname gethostbyaddr getservbyname getservbyport)
 AC_CHECK_FUNCS(select listen bind shutdown close connect setsockopt)
-AC_CHECK_FUNCS(time ctime utime gettimeofday)
+AC_CHECK_FUNCS(time ctime utime gettimeofday getrusage)
 AC_CHECK_FUNCS(chmod fcntl stat fstat getenv putenv strerror)
 AC_CHECK_FUNCS(getpid getgid getsid getpgid getpgrp getuid)
 AC_CHECK_FUNCS(setgroups initgroups nl_langinfo)
 AC_CHECK_FUNCS(strchr strstr strcpy strncpy memcpy memset memmove)
 
+#ifdef SILC_DIST_SIM
 # SIM support checking
 # XXX These needs to be changed as more supported platforms appear.
 # XXX This probably needs to be made platform dependant check.
@@ -174,14 +124,14 @@ AC_CHECK_HEADERS(dlfcn.h,
   [
     AC_CHECK_LIB(dl, dlopen,
       [
-        AC_DEFINE(SILC_SIM)
+        AC_DEFINE([SILC_SIM], [], [HAVE_SIM])
         sim_support=true
         LIBS="$LIBS -ldl"
       ],
       [
         AC_CHECK_LIB(c, dlopen,
           [
-            AC_DEFINE(SILC_SIM)
+            AC_DEFINE([SILC_SIM], [], [HAVE_SIM])
             sim_support=true
           ])
       ])
@@ -190,15 +140,28 @@ AC_CHECK_HEADERS(dlfcn.h,
 AM_CONDITIONAL(SILC_SIM, test x$sim_support = xtrue)
 if test x$sim_support = xtrue; then
   AC_MSG_RESULT(Enabled SIM support.)
+  __SILC_HAVE_SIM="#define __SILC_HAVE_SIM 1"
 else
   AC_MSG_RESULT(No SIM support found.)
 fi
+#endif SILC_DIST_SIM
 
 # lib/contrib conditionals
 #
-AC_CHECK_HEADER(regex.h, have_regex=1, have_regex=0)
+AC_CHECK_HEADER(regex.h,
+  [
+    AC_DEFINE([HAVE_REGEX], [], [HAVE_REGEX])
+    have_regex=1
+  ], have_regex=0
+)
 AM_CONDITIONAL(HAVE_REGEX, test x$have_regex = x1)
-AC_CHECK_FUNC(getopt_long, have_getopt_long=1, have_getopt_long=0)
+
+AC_CHECK_FUNC(getopt_long,
+  [
+    AC_DEFINE([HAVE_GETOPT_LONG], [], [HAVE_GETOPT_LONG])
+    have_getopt_long=1
+  ], have_getopt_long=0
+)
 AM_CONDITIONAL(HAVE_GETOPT_LONG, test x$have_getopt_long = x1)
 
 ##
@@ -216,7 +179,7 @@ AC_ARG_ENABLE(ipv6,
         want_ipv6=true
         check_ipv6=false
        summary_ipv6="yes"
-        AC_DEFINE(HAVE_IPV6)
+        AC_DEFINE([HAVE_IPV6], [], [HAVE_IPV6])
         AC_MSG_RESULT(yes)
         ;;
       *)
@@ -253,7 +216,7 @@ if test x$check_ipv6 = xtrue; then
       int family = AF_INET6;
     ],
     [
-      AC_DEFINE(HAVE_IPV6)
+      AC_DEFINE([HAVE_IPV6], [], [HAVE_IPV6])
       AC_MSG_RESULT(yes)
       summary_ipv6="yes"
     ],
@@ -265,14 +228,16 @@ fi
 #
 AC_MSG_CHECKING(whether to enable debugging)
 summary_debug="no"
+__SILC_ENABLE_DEBUG=""
 AC_ARG_ENABLE(debug,
   [  --enable-debug          enable debugging],
   [
     case "${enableval}" in
       yes)
         AC_MSG_RESULT(yes)
-        AC_DEFINE(SILC_DEBUG)
+        AC_DEFINE([SILC_DEBUG], [], [enable-debug])
        summary_debug="yes"
+        __SILC_ENABLE_DEBUG="#define __SILC_ENABLE_DEBUG 1"
         ;;
       *)
         AC_MSG_RESULT(no)
@@ -283,53 +248,32 @@ AC_ARG_ENABLE(debug,
     AC_MSG_RESULT(no)
   ])
 
-# Stack trace checking
-#
-AC_MSG_CHECKING(whether to enable stack tracing)
-summary_stacktrace="no"
-AC_ARG_ENABLE(stack-trace,
-  [  --enable-stack-trace    enable memory stack trace],
-  [
-    case "${enableval}" in
-    yes)
-      AC_MSG_RESULT(yes)
-      AC_DEFINE(SILC_STACKTRACE)
-      summary_stacktrace="yes"
-      ;;
-    *)
-      AC_MSG_RESULT(no)
-      ;;
-    esac
-  ],
-    AC_MSG_RESULT(no)
-  )
-
 # Disable all assembler optimizations
 #
 AC_MSG_CHECKING(whether to enable assembler optimizations)
-summary_asm="no"
+want_asm=true
 AC_ARG_ENABLE(asm,
   [  --disable-asm           do not use assembler optimizations],
   [
     AC_MSG_RESULT(no)
+    want_asm=false
   ],
   [
     AC_MSG_RESULT(yes)
-    summary_asm="yes"
+    want_asm=true
   ])
 
-
 ##
 ## Compiler and compiler flag checks
 ##
 
 # Function to check if compiler flag works
 # Usage: SILC_ADD_CFLAGS(FLAGS, [ACTION-IF-FAILED])
-AC_DEFUN(SILC_ADD_CFLAGS,
+AC_DEFUN([SILC_ADD_CFLAGS],
 [ tmp_CFLAGS="$CFLAGS"
   CFLAGS="$CFLAGS $1"
   AC_MSG_CHECKING(whether $CC accepts $1 flag)
-  AC_TRY_LINK(, , AC_MSG_RESULT(yes), [AC_MSG_RESULT(no)
+  AC_TRY_LINK([], [], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)
                                       CFLAGS="$tmp_CFLAGS"
                                       $2])
   unset tmp_CFLAGS
@@ -384,6 +328,7 @@ if test "$GCC" -a "$host_cpu" = "sparc64"; then
     )
 fi
 AC_SUBST(FIX_SHA1)
+#endif SILC_DIST_COMPILER
 
 ##
 ##  Installation
@@ -391,13 +336,18 @@ AC_SUBST(FIX_SHA1)
 
 # Default installation destination
 #
+#ifdef SILC_DIST_AUTODIST
+AC_PREFIX_DEFAULT(/usr/local)
+#else !SILC_DIST_AUTODIST
 AC_PREFIX_DEFAULT(/usr/local/silc)
+#endif SILC_DIST_AUTODIST
 if test "x$prefix" != xNONE; then
   silc_prefix="$prefix"
 else
   silc_prefix="$ac_default_prefix"
 fi
 
+#ifndef SILC_DIST_AUTODIST
 # etc directory
 #
 if test "x$sysconfdir" != 'x${prefix}/etc'; then
@@ -418,42 +368,46 @@ AC_ARG_WITH(etcdir,
     esac
   ])
 AC_SUBST(ETCDIR)
-AC_DEFINE_UNQUOTED(SILC_ETCDIR, "$ETCDIR")
+AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
 
-# help directory
+# doc directory
 #
-HELPDIR="$silc_prefix/help"
-AC_ARG_WITH(helpdir,
-  [[  --with-helpdir=DIR      directory for SILC help files [PREFIX/help]]],
+DOCDIR="$silc_prefix/doc"
+AC_ARG_WITH(docdir,
+  [[  --with-docdir=DIR       directory for SILC documentation [PREFIX/doc]]],
   [
     case "$withval" in
       no|yes)
         ;;
       *)
-       HELPDIR="$withval"
-       ;;
+        DOCDIR="$withval"
+        ;;
     esac
   ])
-AC_SUBST(HELPDIR)
-AC_DEFINE_UNQUOTED(SILC_HELPDIR, "$HELPDIR")
+AC_SUBST(DOCDIR)
+AC_DEFINE_UNQUOTED([SILC_DOCDIR], "$DOCDIR", [SILC_DOCDIR])
+#endif SILC_DIST_AUTODIST
 
-# doc directory
+#ifdef SILC_DIST_CLIENT
+# help directory
 #
-DOCDIR="$silc_prefix/doc"
-AC_ARG_WITH(docdir,
-  [[  --with-docdir=DIR       directory for SILC documentation [PREFIX/doc]]],
+HELPDIR="$silc_prefix/help"
+AC_ARG_WITH(helpdir,
+  [[  --with-helpdir=DIR      directory for SILC help files [PREFIX/help]]],
   [
     case "$withval" in
       no|yes)
         ;;
       *)
-        DOCDIR="$withval"
-        ;;
+       HELPDIR="$withval"
+       ;;
     esac
   ])
-AC_SUBST(DOCDIR)
-AC_DEFINE_UNQUOTED(SILC_DOCDIR, "$DOCDIR")
+AC_SUBST(HELPDIR)
+AC_DEFINE_UNQUOTED([SILC_HELPDIR], "$HELPDIR", [SILC_HELPDIR])
+#endif SILC_DIST_CLIENT
 
+#ifdef SILC_DIST_SIM
 # SIM modules directory
 #
 MODULESDIR="$silc_prefix/modules"
@@ -469,8 +423,10 @@ AC_ARG_WITH(simdir,
     esac
   ])
 AC_SUBST(MODULESDIR)
-AC_DEFINE_UNQUOTED(SILC_MODULESDIR, "$MODULESDIR")
+AC_DEFINE_UNQUOTED([SILC_MODULESDIR], "$MODULESDIR", [SILC_MODULESDIR])
+#endif SILC_DIST_SIM
 
+#ifdef SILC_DIST_SERVER
 # Logs directory
 #
 LOGSDIR="$silc_prefix/logs"
@@ -486,7 +442,7 @@ AC_ARG_WITH(logsdir,
     esac
   ])
 AC_SUBST(LOGSDIR)
-AC_DEFINE_UNQUOTED(SILC_LOGSDIR, "$LOGSDIR")
+AC_DEFINE_UNQUOTED([SILC_LOGSDIR], "$LOGSDIR", [SILC_LOGSDIR])
 
 # silcd config file checking
 #
@@ -494,7 +450,7 @@ summary_silcd_configfile="/etc/silc/silcd.conf"
 AC_ARG_WITH(silcd-config-file,
   [[  --with-silcd-config-file=FILE  use FILE as default configuration file
                                  for SILC Server [/etc/silc/silcd.conf]]],
-    AC_DEFINE_UNQUOTED(SILC_SERVER_CONFIG_FILE, "$withval")
+    AC_DEFINE_UNQUOTED([SILC_SERVER_CONFIG_FILE], "$withval", [SILC_SERVER_CONFIG_FILE])
     summary_silcd_configfile="$withval"
   )
 
@@ -519,12 +475,45 @@ AC_ARG_WITH(silcd-pid-file,
     esac
   ])
 AC_SUBST(PIDFILE)
+#endif SILC_DIST_SERVER
 
-
+#ifdef SILC_DIST_COMPILER
 ##
 ##  With/without checkings
 ##
 
+#
+# SILC library checking
+compile_libs=true
+
+#ifndef SILC_DIST_TOOLKIT
+
+AC_ARG_WITH(silc-includes, 
+  [  --with-silc-includes=DIR SILC Toolkit includes [search in DIR]],
+  [ac_silc_includes="$withval"], [ac_silc_includes="no"])
+AC_ARG_WITH(silc-libs,
+  [  --with-silc-libs=DIR     SILC Toolkit libraries [search in DIR]],
+  [ac_silc_libs="$withval"], [ac_silc_libs="no"])
+
+#
+# XXX missing checking the __SILC_WITH_XXX defines from the provided libs
+# in order to determine correct libs to link.
+
+#
+# XXX missing pkg-config check.
+
+if test "$ac_silc_includes" != "no"; then
+  compile_libs=false
+  SILC_LIB_INCLUDES="-I$ac_silc_includes"
+fi
+if test "$ac_silc_libs" != "no"; then
+  compile_libs=false
+  LIBS="$LIBS -L$ac_silc_libs"
+fi
+
+#endif SILC_DIST_TOOLKIT
+
+
 # SOCKS4 support checking
 #
 SAVE_LIBS="$LIBS"
@@ -541,14 +530,14 @@ AC_ARG_WITH(socks4,
       *)
         AC_MSG_RESULT(yes)
         socks=4
-    
+
         if test -d "$withval/include"; then
           CFLAGS="$CFLAGS -I$withval/include"
         fi
         if test -d "$withval/lib"; then
           LDFLAGS="$LDFLAGS -L$withval/lib"
         fi
-    
+
         LIBS="-lsocks $LIBS"
         ;;
     esac
@@ -610,36 +599,37 @@ AC_ARG_WITH(socks5,
   )
 
 if test "x$socks" = "x4"; then
-  AC_DEFINE(SOCKS)
+  AC_DEFINE([SOCKS], [], [Socks])
   CFLAGS="$CFLAGS -Dconnect=Rconnect -Dgetsockname=Rgetsockname -Dbind=Rbind -Daccept=Raccept -Dlisten=Rlisten -Dselect=Rselect"
 fi
 
 if test "x$socks" = "x5"; then
-  AC_DEFINE(SOCKS)
-  AC_DEFINE(SOCKS5)
-  AC_DEFINE(Rconnect, SOCKSconnect)
-  AC_DEFINE(Rgetsockname, SOCKSgetsockname)
-  AC_DEFINE(Rgetpeername, SOCKSgetpeername)
-  AC_DEFINE(Rbind, SOCKSbind)
-  AC_DEFINE(Raccept, SOCKSaccept)
-  AC_DEFINE(Rlisten, SOCKSlisten)
-  AC_DEFINE(Rselect, SOCKSselect)
-  AC_DEFINE(Rrecvfrom, SOCKSrecvfrom)
-  AC_DEFINE(Rsendto, SOCKSsendto)
-  AC_DEFINE(Rrecv, SOCKSrecv)
-  AC_DEFINE(Rsend, SOCKSsend)
-  AC_DEFINE(Rread, SOCKSread)
-  AC_DEFINE(Rwrite, SOCKSwrite)
-  AC_DEFINE(Rrresvport, SOCKSrresvport)
-  AC_DEFINE(Rshutdown, SOCKSshutdown)
-  AC_DEFINE(Rlisten, SOCKSlisten)
-  AC_DEFINE(Rclose, SOCKSclose)
-  AC_DEFINE(Rdup, SOCKSdup)
-  AC_DEFINE(Rdup2, SOCKSdup2)
-  AC_DEFINE(Rfclose, SOCKSfclose)
-  AC_DEFINE(Rgethostbyname, SOCKSgethostbyname)
+  AC_DEFINE([SOCKS], [], [Socks])
+  AC_DEFINE([SOCKS5], [], [Socks5])
+  AC_DEFINE([Rconnect], [SOCKSconnect], [Socks])
+  AC_DEFINE([Rgetsockname], [SOCKSgetsockname], [Socks])
+  AC_DEFINE([Rgetpeername], [SOCKSgetpeername], [Socks])
+  AC_DEFINE([Rbind], [SOCKSbind], [Socks])
+  AC_DEFINE([Raccept], [SOCKSaccept], [Socks])
+  AC_DEFINE([Rlisten], [SOCKSlisten], [Socks])
+  AC_DEFINE([Rselect], [SOCKSselect], [Socks])
+  AC_DEFINE([Rrecvfrom], [SOCKSrecvfrom], [Socks])
+  AC_DEFINE([Rsendto], [SOCKSsendto], [Socks])
+  AC_DEFINE([Rrecv], [SOCKSrecv], [Socks])
+  AC_DEFINE([Rsend], [SOCKSsend], [Socks])
+  AC_DEFINE([Rread], [SOCKSread], [Socks])
+  AC_DEFINE([Rwrite], [SOCKSwrite], [Socks])
+  AC_DEFINE([Rrresvport], [SOCKSrresvport], [Socks])
+  AC_DEFINE([Rshutdown], [SOCKSshutdown], [Socks])
+  AC_DEFINE([Rlisten], [SOCKSlisten], [Socks])
+  AC_DEFINE([Rclose], [SOCKSclose], [Socks])
+  AC_DEFINE([Rdup], [SOCKSdup], [Socks])
+  AC_DEFINE([Rdup2], [SOCKSdup2], [Socks])
+  AC_DEFINE([Rfclose], [SOCKSfclose], [Socks])
+  AC_DEFINE([Rgethostbyname], [SOCKSgethostbyname], [Socks])
 fi
 
+#ifdef SILC_DIST_MATH
 # MP library checking. First check whether user wants to use GMP and use
 # it if found. If not or not defined then compile the MPI library in the
 # source tree.
@@ -658,14 +648,14 @@ AC_ARG_WITH(gmp,
         ;;
       *)
         AC_MSG_RESULT(yes)
-    
+
         if test -d "$withval/include"; then
           CFLAGS="$CFLAGS -I$withval/include"
         fi
         if test -d "$withval/lib"; then
           LDFLAGS="$LDFLAGS -L$withval/lib"
         fi
-    
+
         LIBS="-lgmp $LIBS"
         ;;
     esac
@@ -673,7 +663,7 @@ AC_ARG_WITH(gmp,
     AC_CHECK_LIB(gmp, __gmpz_init,
       [
         mp_gmp=true
-        AC_DEFINE(SILC_MP_GMP)
+        AC_DEFINE([SILC_MP_GMP], [], [GMP])
         AC_MSG_RESULT(Using GMP as a MP library.)
       ],
       [
@@ -688,9 +678,10 @@ AC_ARG_WITH(gmp,
 AM_CONDITIONAL(SILC_MP_GMP, test x$mp_gmp = xtrue)
 AM_CONDITIONAL(SILC_MP_NSS_MPI, test x$mp_gmp = xfalse)
 if test x$mp_gmp = xfalse; then
-  AC_DEFINE(SILC_MP_NSS_MPI)
+  AC_DEFINE([SILC_MP_NSS_MPI], [], [MPI])
   AC_MSG_RESULT(Using NSS MPI as a MP library.)
 fi
+#endif SILC_DIST_MATH
 
 # iconv support
 #
@@ -738,7 +729,7 @@ AC_ARG_WITH(iconv,
   ])
 
 if test x$check_iconv = xtrue; then
-  AC_MSG_RESULT(starting search...)
+  AC_MSG_RESULT(Searching for iconv...)
 
   # XXX
   unset ac_cv_header__iconv_h_ ac_cv_header_iconv_h || true
@@ -759,7 +750,7 @@ if test x$check_iconv = xtrue; then
         ],
         [
           echo "yes"
-          AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
+          AC_DEFINE([HAVE_ICONV], [], [Define if you have the iconv() function.])
           has_iconv=true
           check_iconv=false
         ],
@@ -779,11 +770,11 @@ if test x$check_iconv = xtrue; then
   SAVE_CFLAGS="$CFLAGS"
   SAVE_LDFLAGS="$LDFLAGS"
   SAVE_CPPFLAGS="$CPPFLAGS"
-    
+
   for dir in `echo "/usr/local /usr/pkg /usr/contrib"`; do
     if test x$has_iconv = xfalse; then
       AC_MSG_RESULT(searching in $dir...)
-     
+
       if test -d $dir/include; then
         CPPFLAGS="$CPPFLAGS -I$dir/include"
         CFLAGS="$CFLAGS -I$dir/include"
@@ -791,10 +782,10 @@ if test x$check_iconv = xtrue; then
       if test -d $dir/lib; then
         LDFLAGS="$LDFLAGS -L$dir/lib"
       fi
-    
+
       # XXX
       unset ac_cv_header__iconv_h_ ac_cv_header_iconv_h || true
-      
+
       AC_CHECK_HEADERS(iconv.h,
         [
           LIBS="$LIBS -liconv"
@@ -811,14 +802,14 @@ if test x$check_iconv = xtrue; then
             ],
             [
               echo "yes"
-              has_iconv=true 
-              AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
+              has_iconv=true
+              AC_DEFINE([HAVE_ICONV], [], [Define if you have the iconv() function.])
             ],
             [
               echo "no"
               has_iconv=false
-              LIBS="$SAVE_LIBS"    
+
+              LIBS="$SAVE_LIBS"
               CFLAGS="$SAVE_CFLAGS"
               LDFLAGS="$SAVE_LDFLAGS"
               CPPFLAGS="$SAVE_CPPFLAGS"
@@ -878,7 +869,7 @@ has_threads=false
 AC_MSG_CHECKING(whether to search for POSIX threads)
 AC_ARG_WITH(pthreads,
   [[  --with-pthreads[=DIR]   use POSIX threads [search in DIR/include and DIR/lib]]],
-  [ 
+  [
     case "${withval}" in
       no)
         check_threads=false
@@ -902,7 +893,7 @@ if test x$check_threads = xtrue; then
   SAVE_CFLAGS="$CFLAGS"
   SAVE_LDFLAGS="$LDFLAGS"
   SAVE_CPPFLAGS="$CPPFLAGS"
-  
+
   AC_MSG_RESULT(yes)
   AC_CHECK_HEADERS(pthread.h,
     [
@@ -926,7 +917,7 @@ if test x$check_threads = xtrue; then
       for dir in `echo "/usr/local /usr/pkg /usr/contrib /usr/pkg/pthreads /usr/local/pthreads"`; do
         if test x$has_threads = xfalse; then
           AC_MSG_RESULT(searching in $dir...)
-  
+
           if test -d $dir/include; then
             CPPFLAGS="$CPPFLAGS -I$dir/include"
             CFLAGS="$CFLAGS -I$dir/include"
@@ -939,7 +930,7 @@ if test x$check_threads = xtrue; then
           unset ac_cv_header__pthread_h_ ac_cv_header_pthread_h || true
 
           AC_CHECK_HEADERS(pthread.h,
-            [ 
+            [
               LIBS="$LIBS -lpthread"
               AC_CHECK_LIB(pthread, pthread_attr_init, has_threads=true,
                 [
@@ -964,6 +955,7 @@ else
   has_threads=false
 fi
 
+__SILC_HAVE_PTHREAD=""
 AM_CONDITIONAL(SILC_THREADS, test x$has_threads = xtrue)
 if test x$has_threads = xtrue; then
   CFLAGS="$CFLAGS -D_REENTRANT"
@@ -992,8 +984,9 @@ if test x$has_threads = xtrue; then
    esac
 
   AC_CHECK_FUNC(pthread_create)
-  AC_DEFINE(SILC_HAVE_PTHREAD)
-  AC_DEFINE(SILC_THREADS)
+  AC_DEFINE([SILC_HAVE_PTHREAD], [], [HAVE_PTHREAD])
+  AC_DEFINE([SILC_THREADS], [], [HAVE_THREAD])
+  __SILC_HAVE_PTHREAD="#define __SILC_HAVE_PTHREAD 1"
 fi
 
 # Native WIN32 compilation under cygwin
@@ -1003,7 +996,7 @@ AC_ARG_WITH(win32,
   [  --with-win32            compile native WIN32 (MinGW) code (-mno-cygwin)],
   [
     AC_MSG_RESULT(yes)
-    AC_DEFINE(SILC_WIN32)
+    AC_DEFINE([SILC_WIN32], [], [SILC_WIN32])
     win32_support=true
     CFLAGS="-mno-cygwin $CFLAGS"
     LIBS="$LIBS -lwsock32"
@@ -1025,6 +1018,8 @@ AM_CONDITIONAL(SILC_BEOS, test xfalse = xtrue)
 #
 AM_CONDITIONAL(SILC_OS2, test xfalse = xtrue)
 
+#ifdef SILC_DIST_TOOLKIT
+
 # --without-irssi
 #
 without_irssi=false
@@ -1034,7 +1029,6 @@ AC_ARG_WITH(irssi,
   [
     AC_MSG_RESULT(no)
     without_irssi=true
-    SILC_DIST_SUBDIRS=`echo $SILC_DIST_SUBDIRS | $sedpath -e 's/irssi//'`
   ],
   [
     AC_MSG_RESULT(yes)
@@ -1049,23 +1043,26 @@ AC_ARG_WITH(silcd,
   [
     AC_MSG_RESULT(no)
     without_silcd=true
-    SILC_DIST_SUBDIRS=`echo $SILC_DIST_SUBDIRS | $sedpath -e 's/silcd//'`
   ],
   [
     AC_MSG_RESULT(yes)
   ])
 
+#endif SILC_DIST_TOOLKIT
+
+#ifdef SILC_DIST_CLIENT
 # Irssi perl support
 #
 AC_ARG_WITH(perl,
   [[  --with-perl[=yes|no|module]  Build with Perl support - also specifies
                                if it should be built into main silc binary
                                (static, default) or as a module]])
+#endif SILC_DIST_CLIENT
 
 libtoolfix=true
 AC_MSG_CHECKING(whether to do libtoolfix)
 AC_ARG_WITH(libtoolfix,
-  [  --without-libtoolfix     Do not fix libtool, for package builders],
+  [  --without-libtoolfix    Do not fix libtool, for package builders],
   [
     AC_MSG_RESULT(no)
     libtoolfix=false
@@ -1075,9 +1072,9 @@ AC_ARG_WITH(libtoolfix,
   ])
 
 AC_SUBST(ETCDIR)
-AC_DEFINE_UNQUOTED(SILC_ETCDIR, "$ETCDIR")
-
+AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
 
+#endif SILC_DIST_COMPILER
 
 ##
 ##  Misc
@@ -1085,27 +1082,33 @@ AC_DEFINE_UNQUOTED(SILC_ETCDIR, "$ETCDIR")
 
 # Other configure scripts
 #
+
+#ifdef SILC_DIST_TOOLKIT
 if test x$without_irssi = xfalse; then
-  if test "x$silc_dist" = "xsilc-client" ||
-     test "x$silc_dist" = "xsilc-toolkit"; then
-    AC_CONFIG_SUBDIRS(irssi)
-  fi
+#endif SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_CLIENT
+  AC_CONFIG_SUBDIRS(irssi)
+  irssi="yes"
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_TOOLKIT
 fi
+#endif SILC_DIST_TOOLKIT
 
-if test x$mp_gmp = xfalse; then
-  AC_CONFIG_SUBDIRS(lib/silcmath/mpi)
-fi
+SILC_TOP_SRCDIR=`pwd`
 
-#AC_CONFIG_SUBDIRS(lib/zlib)
+# Included configure scripts
+AD_INCLUDE_CONFIGURE
 
-SILC_TOP_SRCDIR=`pwd`
+#ifdef SILC_DIST_COMPILER
+#
+# Substitutions
+#
 AC_SUBST(SILC_TOP_SRCDIR)
-#SILC_INSTALL_PREFIX=$ac_default_prefix
-#AC_SUBST(SILC_INSTALL_PREFIX)
 AC_SUBST(LIBS)
-INCLUDE_DEFINES_INT="include \$(top_srcdir)/Makefile.defines_int"
-AC_SUBST(INCLUDE_DEFINES_INT)
-AC_SUBST(SILC_DIST_SUBDIRS)
+AC_SUBST(SILC_LIB_INCLUDES)
+AC_SUBST(__SILC_HAVE_PTHREAD)
+AC_SUBST(__SILC_HAVE_SIM)
+AC_SUBST(__SILC_ENABLE_DEBUG)
 
 #
 # Fix the libtool to support run-time configuration.  This allows us
@@ -1117,66 +1120,59 @@ if test x$libtoolfix = xtrue; then
 fi
 AM_CONDITIONAL(SILC_LIBTOOLFIX, test x$libtoolfix = xtrue)
 
+INCLUDE_DEFINES_INT="include \$(top_srcdir)/Makefile.defines_int"
+AC_SUBST(INCLUDE_DEFINES_INT)
+
+#endif SILC_DIST_COMPILER
 
 #
 # Makefile outputs
 #
 AC_CONFIG_FILES(
 Makefile
+#ifdef SILC_DIST_DOC
+doc/Makefile
+#endif SILC_DIST_DOC
+#ifdef SILC_DIST_COMPILER
 Makefile.defines
 Makefile.defines_int
-doc/Makefile
 includes/Makefile
-lib/Makefile
-lib/contrib/Makefile
-lib/silccore/Makefile
-lib/silccore/tests/Makefile
-lib/silccrypt/Makefile
-lib/silccrypt/tests/Makefile
-lib/silcmath/Makefile
-lib/silcmath/mpi/Makefile.defines
-lib/silcmath/mpi/Makefile.defines_int
-lib/silcsim/Makefile
-lib/silcske/Makefile
-lib/silcutil/Makefile
-lib/silcutil/unix/Makefile
-lib/silcutil/win32/Makefile
-lib/silcutil/beos/Makefile
-lib/silcutil/os2/Makefile
-lib/silcutil/epoc/Makefile
-lib/silcsftp/Makefile
-lib/silcsftp/tests/Makefile
-doc/example_silcd.conf
+includes/silcversion.h
 includes/silcincludes.h
-silcmap/Makefile
+#endif SILC_DIST_COMPILER
+#ifdef SILC_DIST_APPS
+apps/Makefile
+#endif SILC_DIST_APPS
 )
 
-if test "x$silc_dist" = "xsilc-client" ||
-   test "x$silc_dist" = "xsilc-toolkit"; then
-  AC_CONFIG_FILES(lib/silcclient/Makefile)
-fi
-
+#ifdef SILC_DIST_TOOLKIT
 if test x$without_irssi = xfalse ; then
-  if test "x$silc_dist" = "xsilc-client" ||
-     test "x$silc_dist" = "xsilc-toolkit"; then
-    AC_CONFIG_FILES(
+#endif SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_CLIENT
+  AC_CONFIG_FILES(
 irssi/Makefile.defines
 irssi/Makefile.defines_int
 )
-  fi
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_TOOLKIT
 fi
+#endif SILC_DIST_TOOLKIT
 
+#ifdef SILC_DIST_TOOLKIT
 if test x$without_silcd = xfalse ; then
-  if test "x$silc_dist" = "xsilc-server" ||
-     test "x$silc_dist" = "xsilc-toolkit"; then
-    AC_CONFIG_FILES(
+#endif SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_SERVER
+  AC_CONFIG_FILES(
 silcd/Makefile
+doc/example_silcd.conf
 )
-  fi
+#endif SILC_DIST_SERVER
+#ifdef SILC_DIST_TOOLKIT
 fi
+#endif SILC_DIST_TOOLKIT
 
-if test "x$silc_dist" = "xsilc-toolkit"; then
-  AC_CONFIG_FILES(
+#ifdef SILC_DIST_TOOLKIT
+AC_CONFIG_FILES(
 silc/Makefile
 win32/Makefile
 win32/libsilc/Makefile
@@ -1185,17 +1181,18 @@ tutorial/Makefile
 tutorial/Makefile.defines
 tutorial/Makefile.defines_int
 )
-fi
+#endif SILC_DIST_TOOLKIT
 
 AC_OUTPUT
 
+#ifdef SILC_DIST_COMPILER
 s_bindir=`eval echo $bindir`;s_bindir=`eval echo $s_bindir`
 s_sbindir=`eval echo $sbindir`;s_sbindir=`eval echo $s_sbindir`
 s_mandir=`eval echo $mandir`;s_mandir=`eval echo $s_mandir`
 s_includedir=`eval echo $includedir`;s_includedir=`eval echo $s_includedir`
 
 echo ""
-echo "SILC Configuration Summary:"
+echo "$PACKAGE Configuration Summary:"
 echo "---------------------------"
 echo " Target host ...................: $target"
 echo " Compiler ......................: $CC"
@@ -1209,53 +1206,76 @@ echo " bin directory .................: $s_bindir"
 echo " sbin directory ................: $s_sbindir"
 echo " etc directory .................: $ETCDIR"
 echo " man directory .................: $s_mandir"
-echo " help directory ................: $HELPDIR"
 echo " doc directory .................: $DOCDIR"
+#ifdef SILC_DIST_CLIENT
+echo " help directory ................: $HELPDIR"
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_SERVER
 echo " logs directory ................: $LOGSDIR"
+#endif SILC_DIST_SERVER
+#ifdef SILC_DIST_SIM
 echo " SIM directory .................: $MODULESDIR"
+#endif SILC_DIST_SIM
+#ifdef SILC_DIST_INCLUDES
 echo " include directory .............: $s_includedir"
+#endif SILC_DIST_INCLUDES
 echo ""
 
-if test "x$silc_dist" = "xsilc-client" ||
-   test "x$silc_dist" = "xsilc-toolkit"; then
-  irssi="yes"
-  if test x$without_irssi = xtrue; then
-    irssi="no"
-  fi
-echo " Compile SILC Client ...........: $irssi"
+#ifdef SILC_DIST_SERVER
+silcd="yes"
+#endif SILC_DIST_SERVER
+
+#ifdef SILC_DIST_TOOLKIT
+if test x$without_irssi = xtrue; then
+  irssi="no"
 fi
+if test x$without_silcd = xtrue; then
+  silcd="no"
+fi
+#endif SILC_DIST_TOOLKIT
 
-if test "x$silc_dist" = "xsilc-server" ||
-   test "x$silc_dist" = "xsilc-toolkit"; then
-  silcd="yes"
-  if test x$without_silcd = xtrue; then
-    silcd="no"
-  fi
+#ifdef SILC_DIST_CLIENT
+echo " Compile SILC Client ...........: $irssi"
+#endif SILC_DIST_CLIENT
+
+#ifdef SILC_DIST_SERVER
 echo " Compile SILC Server ...........: $silcd"
 echo " Server configuration file .....: $summary_silcd_configfile"
 echo " Server PID file ...............: $PIDFILE"
-fi
+#endif SILC_DIST_SERVER
 
+#ifdef SILC_DIST_SIM
 if test x$sim_support = xfalse; then
   sim_support="no"
 else
   sim_support="yes"
 fi
+echo " SIM support ...................: $sim_support"
+#endif SILC_DIST_SIM
+
+echo " IPv6 support ..................: $summary_ipv6"
+
 if test x$has_iconv = xfalse; then
   iconv_support="no"
 else
   iconv_support="yes"
 fi
-echo " SIM support ...................: $sim_support"
-echo " IPv6 support ..................: $summary_ipv6"
 echo " Iconv support .................: $iconv_support"
+
+if test x$want_asm = xfalse; then
+  summary_asm="no"
+else
+  summary_asm="yes"
+fi
 echo " Assembler optimizations .......: $summary_asm"
 
+#ifdef SILC_DIST_MATH
 mp="MPI"
 if test x$mp_gmp = xtrue; then
   mp="GMP"
 fi
 echo " Arithmetic library ............: $mp"
+#endif SILC_DIST_MATH
 
 threads="no"
 if test x$has_threads = xtrue; then
@@ -1263,10 +1283,7 @@ if test x$has_threads = xtrue; then
 fi
 echo " Multi-threads support .........: $threads"
 echo " Debugging enabled .............: $summary_debug"
-echo " Stack-trace enabled ...........: $summary_stacktrace"
 echo ""
-if test "x$silc_dist" = "xsilc-client"; then
-  echo "Compile the sources with 'make' or 'gmake' command (GNU make is required)."
-else
-  echo "Compile the sources with 'make' or 'gmake' command."
-fi
+echo "Compile the sources with 'make' or 'gmake' command."
+#endif SILC_DIST_COMPILER
+
diff --git a/distdir/BSD b/distdir/BSD
new file mode 100644 (file)
index 0000000..5329321
--- /dev/null
@@ -0,0 +1,25 @@
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+   3. The name of the author may not be used to endorse or promote
+      products derived from this software without specific prior written
+      permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/distdir/BSD-header b/distdir/BSD-header
new file mode 100644 (file)
index 0000000..8aa2ac3
--- /dev/null
@@ -0,0 +1,8 @@
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the conditions listed in the
+  COPYING file are met.
+
+
+
diff --git a/distdir/GPL b/distdir/GPL
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/distdir/GPL-header b/distdir/GPL-header
new file mode 100644 (file)
index 0000000..f217f10
--- /dev/null
@@ -0,0 +1,8 @@
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
diff --git a/distdir/autodist b/distdir/autodist
new file mode 100644 (file)
index 0000000..0aa0831
--- /dev/null
@@ -0,0 +1,18 @@
+name SILC Autodist
+package autodist
+bug-report autodist-bugs@silcnet.org
+
+license apps/autodist/COPYING
+license-header distdir/GPL-header distdir/BSD-header
+
+define SILC_DIST_AUTODIST
+define SILC_DIST_APPS
+
+include apps/autodist/INSTALL INSTALL
+include apps/autodist/AUTHORS AUTHORS
+include apps/autodist/README README
+exclude apps/autodist/INSTALL apps/autodist/AUTHORS apps/autodist/README
+exclude TODO README.* ltmain.sh
+
+noprocess apps/autodist/doc apps/autodist/tests
+
diff --git a/distdir/autodist.conf b/distdir/autodist.conf
new file mode 100644 (file)
index 0000000..8a279ae
--- /dev/null
@@ -0,0 +1,49 @@
+# Autodist configuration file
+
+# By default distdef prefix is '_DIST_'.  To add your own prefix set the
+# prefix here.  NOTE: Remember to change all 'define' directives in
+# distributions to use the new prefix if you change it.  Example:
+#
+# DISTPREFIX="SILC"
+#
+# Will set the distdef prefix as 'SILC_DIST_'.
+# 
+DISTPREFIX="SILC"
+
+# The distdef header will be created by the Autodist.  It need to be included
+# in the source code in order for the preprocessor to respect distdef 
+# conditionals in source code.  Example:
+#
+# DISTDEFS="include/distdefs.h"
+#
+DISTDEFS="includes/silcdistdefs.h"
+
+# Location of the aclocal tool.  If this is omitted the Autodist will not
+# run aclocal.  User need to run it manually then.
+#
+ACLOCAL="aclocal"
+
+# Location of the autoheader tool.  If this is omitted the Autodist will not
+# run autoheader.  User need to run it manually then.
+#
+AUTOHEADER="autoheader"
+
+# Location of the autoconf tool.  If this is omitted the Autodist will not
+# run autoconf.  User need to run it manually then.
+#
+AUTOCONF="autoconf"
+
+# Location of the automake tool.  If this is omitted the Autodist will not
+# run automake.  User need to run it manually then.
+#
+AUTOMAKE="automake"
+
+# Location of the libtoolize tool.  This option should be omitted if your
+# source tree does not use libtool.
+#
+LIBTOOLIZE="libtoolize --automake --copy"
+
+# Location of the make program.  This must be specified in order to be 
+# able to create distributions.
+#
+MAKE="make"
diff --git a/distdir/client b/distdir/client
new file mode 100644 (file)
index 0000000..76ec28b
--- /dev/null
@@ -0,0 +1,7 @@
+name Client
+package silc-client
+bug-report silc-devel@lists.silcnet.org
+inherit common
+define SILC_DIST_CLIENT
+define SILC_DIST_CLIENTLIB
+pre-hook distdir/pre-run
diff --git a/distdir/common b/distdir/common
new file mode 100644 (file)
index 0000000..39a2a5b
--- /dev/null
@@ -0,0 +1,10 @@
+# Common SILC source tree distdefs
+option template
+define SILC_DIST_SILC
+define SILC_DIST_LIB
+define SILC_DIST_INCLUDES
+define SILC_DIST_DOC
+define SILC_DIST_SIM
+define SILC_DIST_MPI
+define SILC_DIST_MATH
+define SILC_DIST_COMPILER
diff --git a/distdir/default b/distdir/default
new file mode 100644 (file)
index 0000000..a000fd9
--- /dev/null
@@ -0,0 +1,16 @@
+# Default distribution
+#
+# NOTE: By default, this distribution cannot be packaged.  Take away the
+# 'no-dist option if you whish to use this as a normal distribution.
+#
+# If you add new distributions into distdir/ inherit them here.
+#
+option no-dist
+
+# Default distribution for preparing raw CVS sources.
+inherit common
+inherit client
+inherit server
+inherit toolkit
+define SILC_DIST_INPLACE
+pre-hook distdir/pre-run
diff --git a/distdir/pre-run b/distdir/pre-run
new file mode 100644 (file)
index 0000000..cc716ca
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+distribution=$1
+dist_version=$2
+package=$3
+
+# preparing irssi
+echo "Preparing irssi"
+file=irssi/irssi-version.h.in
+touch $file
+cd irssi
+ln -fs ../Makefile.defines.in Makefile.defines.in
+ln -fs ../Makefile.defines_int.in Makefile.defines_int.in
+sh autogen.sh 2>/dev/null 1>/dev/null
+cd ..
+version_date=`date +%Y%m%d`
+echo "/* automatically created by autogen.sh */" > $file
+echo "#define IRSSI_VERSION \"$dist_version (Irssi base: @VERSION@ - SILC base: SILC $dist_version)\"" >>$file
+echo "#define IRSSI_VERSION_DATE $version_date" >> $file
+echo "#define IRSSI_VERSION_TIME $version_date" >> $file
diff --git a/distdir/server b/distdir/server
new file mode 100644 (file)
index 0000000..15eaecc
--- /dev/null
@@ -0,0 +1,7 @@
+name Server
+package silc-server
+bug-report silc-devel@lists.silcnet.org
+license distdir/BSD
+license-header distdir/GPL-header distdir/BSD-header
+inherit common
+define SILC_DIST_SERVER
diff --git a/distdir/toolkit b/distdir/toolkit
new file mode 100644 (file)
index 0000000..180ab29
--- /dev/null
@@ -0,0 +1,13 @@
+name Toolkit
+package silc-toolkit
+bug-report silc-devel@lists.silcnet.org
+inherit common
+inherit client
+inherit server
+define SILC_DIST_TOOLKIT
+include README.CVS
+include README.WIN32
+include README.MACOSX
+include silcer
+include tutorial
+pre-hook distdir/pre-run
diff --git a/distributions b/distributions
deleted file mode 100644 (file)
index a0a16cb..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#
-# Distributions
-#
-# Distributions file describing the different distributions that are
-# created out of the SILC source tree.  The ./prepare script will read
-# this file to determine what kind of distributions are created.
-#
-# Give the name of the distribution and the version as arguments to the
-# ./prepare script to prepare the source tree for the specific
-# distribution.
-#
-# The format of this file is as follows:
-#
-# <name>_SUBDIRS                       Subdirs for the distribution
-# <name>_SUBDIRS_<dir>                 Subdirs under <dir>
-# <name>_DISTLABEL                     Preprocessor label
-# <name>_EXTRA_DIST                    List of extra files or directories
-#
-# The _SUBDIRS define all the subdirectories that the Makefile should
-# traverse.  The SUBDIRS_<dir> defines all subdirectories in the 
-# subdirectory <dir>.  The DISTLABEL defines a preprocessor label
-# that can be used in the source code like `#ifdef SILC_DIST_CLIENT' to
-# define code only for the specific distribution.  The label can also be
-# used in the Makefiles by `if SILC_DIST_CLIENT' to define something in
-# the Makefile only for the specific distribution.
-#
-# The DISTRIBUTIONS defines all distributions in this file.  The
-# EXTRA_DIST is used to add extra files or directories to the
-# distribution. The files may be in subdirectories.
-#
-# NOTE: For now this supports only one sublevel of the directories.
-#       Also make sure that the <dir> directory includes Makefile.am.pre
-#       instead of Makefile.am, otherwise it won't work.  The Makefile.am.pre
-#       must have DIST_SUBDIRS = SILC_DISTRIBUTIONS_SUBDIRS line in it.
-#
-# NOTE: Also note that if any subdirectory has Makefile.am.pre then you
-#       must list it here as <name>_SUBDIRS_<dir>. To define all sub
-#       directories use $(COMMONDIRS) that must be defined in the Makefile
-#       and list all subdirs.
-#
-# Example:
-#
-# xyz_SUBDIRS=lib irssi doc includes
-# xyz_SUBDIRS_lib=$(COMMONDIRS)
-# xyz_DISTLABEL=SILC_DIST_XYZ
-# xyz_EXTRA_DIST=README.XYZ
-#
-# To prepare the distribution give command ./prepare xyz 1.0.4
-#
-
-# Default Toolkit distribution
-toolkit_SUBDIRS=lib irssi silc silcd doc includes win32
-toolkit_SUBDIRS_lib=$(COMMONDIRS)
-toolkit_SUBDIRS_doc=$(COMMONDIRS)
-toolkit_DISTLABEL=SILC_DIST_TOOLKIT
-toolkit_EXTRA_DIST=README.CVS README.WIN32 README.MACOSX silcer tutorial
-
-# Irssi SILC Client distribution
-client_SUBDIRS=lib irssi doc includes
-client_SUBDIRS_lib=contrib silccore silccrypt silcsim silcmath silcske silcutil silcclient silcsftp
-client_SUBDIRS_doc=$(COMMONDIRS)
-client_DISTLABEL=SILC_DIST_CLIENT
-client_EXTRA_DIST=#
-
-# SILC Server distribution
-server_SUBDIRS=lib silcd doc includes
-server_SUBDIRS_lib=contrib silccore silccrypt silcsim silcmath silcske silcutil silcsftp
-server_SUBDIRS_doc=$(COMMONDIRS)
-server_DISTLABEL=SILC_DIST_SERVER
-server_EXTRA_DIST=#
-
-# Native WIN32 SILC library distribution (will include only the libraries)
-# XXX This is not really used at all!
-win32dll_SUBDIRS=lib doc includes
-win32dll_SUBDIRS_lib=silccore silccrypt silcsim silcmath silcske silcutil silcclient
-win32dll_SUBDIRS_doc=$(COMMONDIRS)
-win32dll_DISTLABEL=SILC_DIST_WIN32DLL
-win32dll_EXTRA_DIST=README.CVS README.WIN32
-
-DISTRIBUTIONS=toolkit client server win32dll
diff --git a/doc/FAQ b/doc/FAQ
index 9993c3f15ce1bce905c32efaf27165dae9e6eb4e..396daa4fe51fd81bed7deac27f66fc2efc8ac8e7 100644 (file)
--- a/doc/FAQ
+++ b/doc/FAQ
    Q: Does SILC support moderated channels?
    A: Yes. Channel founder can moderate both normal users and channel
    operators so that they cannot talk on the channel. It is also possible
-   to queit one specific user on the channel if needed.
+   to quiet one specific user on the channel if needed.
 
    Q: What does the "watching" mean?
    A: You can set a "watch" list for yourself in the server. This means
similarity index 56%
rename from doc/Makefile.am.pre
rename to doc/Makefile.ad
index edb11a70f8c0119aced30dc70260fb06996a9a73..f6c1b5f3377c8d90c3a067c668e7874d0b1f6c33 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 - 2001 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-COMMONDIRS = .
-SUBDIRS = SILC_DISTRIBUTION_SUBDIRS
-DIST_SUBDIRS = SILC_DISTRIBUTION_SUBDIRS
-makerfc = ../scripts/makerfc
-
 all:
        touch draft-riikonen-silc-spec-08.txt
-       touch draft-riikonen-silc-pp-08.txt
-       touch draft-riikonen-silc-ke-auth-07.txt
+       touch draft-riikonen-silc-pp-09.txt
+       touch draft-riikonen-silc-ke-auth-08.txt
        touch draft-riikonen-silc-commands-06.txt
-       touch draft-riikonen-silc-flags-payloads-03.txt
-       touch draft-riikonen-presence-attrs-02.txt
+       touch draft-riikonen-silc-flags-payloads-04.txt
+       touch draft-riikonen-presence-attrs-03.txt
+
+#ifdef SILC_DIST_TOOLKIT
+makerfc = $(SILC_TOP_SRCDIR)/scripts/makerfc
 
-if SILC_DIST_TOOLKIT
 toolkit-ref-html:
        -@if test -f $(SILC_TOP_SRCDIR)/util/robodoc/Source/robodoc ; then \
          echo Generating Toolkit Reference Manual ; \
@@ -55,51 +51,52 @@ toolkit-ref-pdf:
         fi
 
 dist-hook:
+       rm -rf `find $(top_distdir)/doc -name CVS`
        $(SILC_TOP_SRCDIR)/scripts/manpages.pl
        touch draft-riikonen-silc-spec-08.txt
-       touch draft-riikonen-silc-pp-08.txt
-       touch draft-riikonen-silc-ke-auth-07.txt
+       touch draft-riikonen-silc-pp-09.txt
+       touch draft-riikonen-silc-ke-auth-08.txt
        touch draft-riikonen-silc-commands-06.txt
-       touch draft-riikonen-silc-flags-payloads-03.txt
-       touch draft-riikonen-presence-attrs-02.txt
+       touch draft-riikonen-silc-flags-payloads-04.txt
+       touch draft-riikonen-presence-attrs-03.txt
        $(makerfc) draft-riikonen-silc-spec-08.nroff \
                draft-riikonen-silc-spec-08.txt
-       $(makerfc) draft-riikonen-silc-pp-08.nroff \
-               draft-riikonen-silc-pp-08.txt
-       $(makerfc) draft-riikonen-silc-ke-auth-07.nroff \
-               draft-riikonen-silc-ke-auth-07.txt
+       $(makerfc) draft-riikonen-silc-pp-09.nroff \
+               draft-riikonen-silc-pp-09.txt
+       $(makerfc) draft-riikonen-silc-ke-auth-08.nroff \
+               draft-riikonen-silc-ke-auth-08.txt
        $(makerfc) draft-riikonen-silc-commands-06.nroff \
                draft-riikonen-silc-commands-06.txt
-       $(makerfc) draft-riikonen-silc-flags-payloads-03.nroff \
-               draft-riikonen-silc-flags-payloads-03.txt
-       $(makerfc) draft-riikonen-presence-attrs-02.nroff \
-               draft-riikonen-presence-attrs-02.txt
+       $(makerfc) draft-riikonen-silc-flags-payloads-04.nroff \
+               draft-riikonen-silc-flags-payloads-04.txt
+       $(makerfc) draft-riikonen-presence-attrs-03.nroff \
+               draft-riikonen-presence-attrs-03.txt
 
-else
+#else !SILC_DIST_TOOLKIT
 dist-hook:
+       rm -rf `find $(top_distdir)/doc -name CVS`
        $(SILC_TOP_SRCDIR)/scripts/manpages.pl
        rm draft-riikonen*.txt
        touch draft-riikonen-silc-spec-08.txt
-       touch draft-riikonen-silc-pp-08.txt
-       touch draft-riikonen-silc-ke-auth-07.txt
+       touch draft-riikonen-silc-pp-09.txt
+       touch draft-riikonen-silc-ke-auth-08.txt
        touch draft-riikonen-silc-commands-06.txt
        touch draft-riikonen-silc-flags-payloads-04.txt
-       touch draft-riikonen-presence-attrs-02.txt
-endif
-
-if SILC_DIST_TOOLKIT
-SILC_EXTRA_DIST = toolkit examples silc.1 silcd.8 silcd.conf.5
-else
-if SILC_DIST_SERVER
-SILC_EXTRA_DIST = examples silcd.8 silcd.conf.5
-else
-SILC_EXTRA_DIST = silc.1
-endif
-endif
+       touch draft-riikonen-presence-attrs-03.txt
+#endif SILC_DIST_TOOLKIT
 
-EXTRA_DIST = \
-       CodingStyle \
-       FAQ \
-       example_silcd.conf \
-       silcalgs.conf \
-       draft-riikonen*.txt $(SILC_EXTRA_DIST)
+EXTRA_DIST =                   \
+#ifdef SILC_DIST_CLIENT
+       silc.1                  \
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_SERVER
+       examples silcd.8 silcd.conf.5   \
+#endif SILC_DIST_SERVER
+#ifdef SILC_DIST_TOOLKIT
+       toolkit                 \
+       CodingStyle             \
+#endif SILC_DIST_TOOLKIT
+       FAQ                     \
+       example_silcd.conf      \
+       silcalgs.conf           \
+       draft-riikonen*.txt
diff --git a/doc/draft-riikonen-presence-attrs-03.nroff b/doc/draft-riikonen-presence-attrs-03.nroff
new file mode 100644 (file)
index 0000000..1f83ded
--- /dev/null
@@ -0,0 +1,669 @@
+.pl 10.0i
+.po 0
+.ll 7.2i
+.lt 7.2i
+.nr LL 7.2i
+.nr LT 7.2i
+.ds LF Riikonen
+.ds RF FORMFEED[Page %]
+.ds CF
+.ds LH Internet Draft
+.ds RH 2 February 2004
+.ds CH
+.na
+.hy 0
+.in 0
+.nf
+Network Working Group                                        P. Riikonen
+Internet-Draft
+draft-riikonen-presence-attrs-03.txt                     2 February 2004
+Expires: 2 August 2004
+
+.in 3
+
+.ce 2
+User Online Presence and Information Attributes
+<draft-riikonen-presence-attrs-03.txt>
+
+.ti 0
+Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with   
+all provisions of Section 10 of RFC 2026.  Internet-Drafts are   
+working documents of the Internet Engineering Task Force (IETF), its   
+areas, and its working groups.  Note that other groups may also   
+distribute working documents as Internet-Drafts.   
+
+Internet-Drafts are draft documents valid for a maximum of six months   
+and may be updated, replaced, or obsoleted by other documents at any   
+time.  It is inappropriate to use Internet-Drafts as reference   
+material or to cite them other than as "work in progress."   
+
+The list of current Internet-Drafts can be accessed at   
+http://www.ietf.org/ietf/1id-abstracts.txt   
+
+The list of Internet-Draft Shadow Directories can be accessed at   
+http://www.ietf.org/shadow.html   
+
+The distribution of this memo is unlimited.  
+
+
+.ti 0
+Abstract
+
+This document defines set of attributes that can represent the online
+user's presence in a network, and to provide general information about
+the user.  The purpose is to provide a generic mechanism to share
+online presence and status, and general information about the user
+to be used in several kind of network protocols and applications.
+These attributes could be used by for example chat and conferencing
+protocols (such as Instant Message protocols), network games, and
+other similar network protocols and applications that has online
+users in a network.
+
+
+
+
+
+
+
+.ti 0
+Table of Contents
+
+.nf
+1 Introduction ..................................................  2
+  1.1 Requirements Terminology ..................................  2
+2 Attributes Concept ............................................  3
+  2.1 Requesting Attributes .....................................  3
+  2.2 Replying Attributes .......................................  3
+  2.3 Attribute Data Types ......................................  4
+  2.4 Attribute Payload .........................................  4
+  2.5 Attributes ................................................  5
+3 Security Considerations .......................................  11
+4 References ....................................................  12
+5 Author's Address ..............................................  13
+6 Full Copyright Statement ......................................  13
+
+
+.ti 0
+1. Introduction
+
+This document defines set of attributes that can represent the online
+user's presence in a network, and to provide general information about
+the user.  The purpose is to provide a generic mechanism to share
+online presence and status, and general information about the user
+to be used in several kind of network protocols and applications.
+These attributes could be used by for example chat and conferencing
+protocols (such as Instant Message protocols), network games, and
+other similar network protocols and applications that has online
+users in a network.
+
+This document does not define these attributes to be used in any
+specific protocol, but assumes that they can be used generally in
+any kind of online network protocol.  Furthermore, the document
+pays attention to special needs of various protocols, such as
+mobile network protocols, which requires the attributes to be
+both robust and compact.  The attributes are also considered to be
+easily implementable and for this reason a clear and robust structure
+was chosen for the attributes.
+
+This document is strongly influenced by Wireless Village Initiative
+where similar attributes are defined, and credits for the ideas are
+due there.  However, they are defined only in the context of the
+Wireless Village, and the format of the attributes used is not
+suitable for general purpose usage.
+
+
+.ti 0
+1.1 Requirements Terminology
+
+The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED, 
+MAY, and OPTIONAL, when they appear in this document, are to be
+interpreted as described in [RFC2119].
+
+
+.ti 0
+2 Attributes Concept
+
+Many network protocols needs a way to transfer and retrieve status
+information about users in a network.  For example, many chat and
+conferencing protocols such as IRC, and all Instant Message (IM)
+protocols, such as ICQ has a way to retrieve presence and status
+information about the users in the network.  This could be added to
+several other kind of network protocols as well, and for this reason
+a defined mechanism to provide these informations is needed.
+
+The attributes are usually requested by an entity in the network
+from other entity, usually a user or end user's device in the network.
+The recipient then replies to each of the requested attributes and
+sends the reply to the requester.
+
+This document does not define the actual transport for requesting and
+providing the replies to the requests, since this is irrelevant.
+This document defines a payload for requesting, and providing the
+information, but how the payload is transported is not defined in
+this document.  In a client-server network model the user requesting
+attributes usually destine the request to a remote user and the
+server relays the attributes to the remote user.  It is also possible
+that the concept is not user-to-user, but the server replies to the
+requested attributes on behalf of the user.
+
+
+.ti 0
+2.1 Requesting Attributes
+
+When an entity requests attributes from a user in the network,
+it assembles a list of Attribute Payloads, and sets the requested
+attribute value into the payload.  Each requested attribute is a separate
+Attribute Payload and they MUST be appended one after the other.  The
+requester need to understand that the recipient may not understand all
+the requested attributes, and may not reply to all of the requested
+attributes.  The requester also need to understand that the recipient
+may reply with additional attributes that were not requested.
+
+
+.ti 0
+2.2 Replying Attributes
+
+When en entity receives the Attribute Payloads it parses them one after
+the other.  The entity can parse each of the Attribute Payload separately
+since it knows the length of the current attribute; next attribute
+begins after the current attribute ends.  The entity then checks the
+requested attribute and SHOULD reply either with valid value or with
+an indication that the attribute is unsupported or unknown.  It is
+also possible to reply with additional attributes that were not
+requested.
+
+When replying to the requested attributes the entity assembles a list
+of Attribute Payloads, each including the attribute type and the
+actual attribute data.
+
+
+.ti 0
+2.3 Attribute Data Types
+
+This section defines basic data types that can appear in the attributes
+in this document.
+
+All integer values are stored in the MSB first order.  The size of the
+integer is provided separately with the attribute.  Integer is
+represented as "integer" in this documentation.
+
+Strings MUST be UTF-8 [RFC2279] encoded, and include 2 bytes length
+field indicating the length of the string.  Hence, when "string" value
+appears in this documentation it is encoded as:
+
+.in 6
+Length       Type       Value
+2 bytes      integer    Length of String field
+variable     UTF-8      String
+.in 3
+
+If string is not present then the length field includes zero (0)
+value.
+
+Boolean value is represented as "boolean" and its size is 1 byte.
+Value 0x00 indicates false value and value 0x01 indicates true value.
+
+
+.ti 0
+2.4 Attribute Payload
+
+The Attribute Payload is used to request an attribute, and to reply
+to the requested attribute.  One payload includes one attribute.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|   Attribute   |   Attr Flags  |        Attribute Length       |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                        Attribute Data                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 1:  Attribute Payload
+
+
+.in 6
+o Attribute (1 byte) - Indicates the attribute included in this
+  Attribute Payload.
+
+o Attribute Flags (1 byte) - Indicates the flags associated
+  with this attribute.  The following flags are defined:
+
+    0x01        ATTRIBUTE_FLAG_INVALID
+
+      The attribute value in Attribute Data is invalid, or
+      unknown.  This may be set to indicate that a requested
+      attribute is not available, its value is unknown, or
+      sender does not understand it.
+
+    0x02        ATTRIBUTE_FLAG_VALID
+
+      The attribute value is included in the Attribute Data.
+
+  When sending this payload to request attributes this value
+  MUST be set to zero (0) value.  When sending a reply to the
+  request this field MUST NOT include a zero (0) value.
+
+o Attribute Length (2 bytes) - Indicates the length of the
+  Attribute Data field, not including any other field.
+
+o Attribute Data (variable length) - The Attribute Data.
+  The contents of this field is attribute specific, defined
+  subsequently.
+.in 3
+
+
+.ti 0
+2.5 Attributes
+
+The following values can appear in the Attribute field in the
+Attribute Payload to indicate the content of the attribute.  The
+format of the attribute data is represented as length, type and
+value.  Example:
+
+.in 6
+Length       Type       Value
+2 bytes      integer    Some integer value
+variable     string     Some string
+1 byte       boolean    Boolean value
+.in 3
+
+When sending multiple Attribute Payloads it is possible to include
+multiple same attributes in the packet.
+
+
+.in 6
+0    ATTRIBUTE_NONE
+
+     This attribute is reserved and it is never sent.
+
+
+1    ATTRIBUTE_USER_INFO
+
+     This attribute includes general information about the user, their
+     name and contact information.  The content of this attribute is
+     a VCard version 3.0 as defined in RFC 2426 [RFC2426] and RFC 2425
+     [RFC2425].  Note that some of the information that VCard provides
+     can be also provided in the means of providing other attributes.
+     The rationale for this is that the VCard does not provide all the
+     information, or with the required precision that may be desired in
+     some applications.  It is therefore RECOMMENDED that this attribute
+     would be used to provide only basic and constant user information,
+     such as name and contact information, but not online status 
+     information.
+
+     Length       Type       Value
+     variable     VCard      Basic user information
+
+
+2    ATTRIBUTE_SERVICE
+
+     This attribute indicates a service in the Internet that the user
+     is currently using or has logged in.  It also shows when the user
+     started using the service, and how long user has been idle in the
+     service.  The value of this attribute is as follows:
+
+     Length       Type       Value
+     4 bytes      integer    Service Port (IANA specified)
+     variable     string     Service Address
+     1 byte       boolean    Online status.  If this is set to
+                             0x01 (true) it means the user is online
+                             in the service.  Set to 0x00 (false) when
+                             out of reach.
+     variable     string     Signon date and time, UTC date, format as
+                             in ISO 8601
+     4 bytes      integer    Idle time
+
+
+3    ATTRIBUTE_STATUS_MOOD
+
+     This attribute indicates the mood of the user.  It can indicate
+     whether the user is eager to participate in the network.  The
+     value of this attribute is as follows:
+
+     Length       Type       Value
+     4 bytes      integer    Mood mask (values ORed together)
+
+     The following mood values are defined:
+
+     0x00000000   MOOD_NORMAL       No specific mood, normal mood
+     0x00000001   MOOD_HAPPY        The user feels happy
+     0x00000002   MOOD_SAD          The user feels sad
+     0x00000004   MOOD_ANGRY        The user feels angry
+     0x00000008   MOOD_JEALOUS      The user feels jealous
+     0x00000010   MOOD_ASHAMED      The user feels ashamed
+     0x00000020   MOOD_INVINCIBLE   The user feels invincible
+     0x00000040   MOOD_INLOVE       The user feels being in love
+     0x00000080   MOOD_SLEEPY       The user feels sleepy
+     0x00000100   MOOD_BORED        The user feels bored
+     0x00000200   MOOD_EXCITED      The user feels excited
+     0x00000400   MOOD_ANXIOUS      The user feels anxious
+
+
+4    ATTRIBUTE_STATUS_FREETEXT
+
+     This attribute includes the user's online status free text.  It
+     can provide personal status as a text message.  The contents of
+     this attribute is a UTF-8 encoded free text string.
+
+     Length       Type       Value
+     variable     string     Free text status string
+
+
+5    ATTRIBUTE_STATUS_MESSAGE
+
+     This attribute includes the user's online status message.  It
+     could provide for example a multi media message showing the status
+     of the user.  The contents of this attribute is a MIME object,
+     which can be used to provide for example video, audio, image or
+     other similar status message.  It could also provide a reference
+     to the message, for example an URL address.
+
+     Length       Type       Value
+     variable     MIME       Status message as MIME object
+
+
+6    ATTRIBUTE_PREFERRED_LANGUAGE
+
+     This attribute indicates the preferred language to be used when
+     communicating.  The encoding of this attribute is as follows:
+
+     Length       Type       Value
+     variable     string     ISO 639-2/T three letter code
+
+
+7    ATTRIBUTE_PREFERRED_CONTACT
+
+     This attribute indicates the preferred contact methods.  It can
+     indicate the method the user prefers when contacting.  The value
+     of this attribute is as follows:
+
+     Length       Type       Value
+     4 bytes      integer    Contact mask (values ORed together)
+
+     The following contact methods are defined:
+
+     0x00000000   CONTACT_NONE     No specific preferred contact method
+     0x00000001   CONTACT_EMAIL    Email is preferred
+     0x00000002   CONTACT_CALL     Phone call is preferred
+     0x00000004   CONTACT_PAGE     Paging is preferred
+     0x00000008   CONTACT_SMS      SMS is preferred
+     0x00000010   CONTACT_MMS      MMS is preferred
+     0x00000020   CONTACT_CHAT     Chatting is preferred
+     0x00000040   CONTACT_VIDEO    Video conferencing is preferred
+
+
+8    ATTRIBUTE_TIMEZONE
+
+     This attribute can be used to provide the current local time for
+     the user.  The contents of this attribute is a UTF-8 encoded
+     string and the format of the string is UTC time zone defined
+     in the ISO 8601.
+
+     Length       Type       Value
+     variable     string     UTC date, format as in ISO 8601
+
+     Note that ATTRIBUTE_USER_INFO may also provide this information.
+     However it is RECOMMENDED that this attribute is used when
+     current time zone information is provided.
+
+
+9    ATTRIBUTE_GEOLOCATION
+
+     This attribute can be used to provide measured global location of
+     the user.  How this information is gathered is out of scope of
+     this document.  The attribute can provide latitude and longitude
+     lateral positions, but also a vertical position.  A parameter
+     describing the accuracy of the information can also be provided.
+
+     Length       Type       Value
+     variable     string     Longitude (ex. 31 17 14.321W)
+     variable     string     Latitude (ex. 12 11 21.2N)
+     variable     string     Altitude
+     variable     string     Accuracy in meters
+
+     Note that ATTRIBUTE_USER_INFO may also provide this information,
+     however it does not have the vertical position, or the accuracy
+     parameter.  It is RECOMMENDED that this attribute is used when
+     providing current global position information.
+
+
+10   ATTRIBUTE_DEVICE_INFO
+
+     This attribute includes information about the user's device.
+     The encoding of this attribute is as follows:
+
+     Length       Type       Value
+     4 bytes      integer    Device type
+     variable     string     Name of the device manufacturer
+     variable     string     Device version
+     variable     string     Device model
+     variable     string     Device language (ISO 639-2/T)
+
+     The following Device types are defined:
+
+     0    DEVICE_COMPUTER        Device is a computer
+     1    DEVICE_MOBILE_PHONE    Device is a mobile phone
+     2    DEVICE_PDA             Device is a PDA
+     3    DEVICE_TERMINAL        Device is a terminal
+
+
+11   ATTRIBUTE_EXTENSION
+
+     This attribute indicates that the attribute value is vendor,
+     application or service specific attribute extension.  This field
+     MUST include a MIME object, which is the extension value.  This
+     document does not specify any explicit MIME objects for this
+     attribute.
+
+     Length       Type       Value
+     variable     MIME       Attribute extension as MIME object
+
+
+12   ATTRIBUTE_USER_PUBLIC_KEY
+
+     This attribute includes the user's public key or certificate.
+     As the public key and certificate format depends on which sort
+     of algorithm or certificate encoding user is using we need to
+     define a mechanism to differentiate the public key types from
+     each other.  This document specifies the most common public keys
+     and certificates.  This attribute can be used to deliver the
+     user's public key, and it MUST be present if also the
+     ATTRIBUTE_USER_DIGITAL_SIGNATURE is present.  Note that the
+     recipient of this attribute SHOULD verify the public key from
+     a third party, for example from Certification Authority.  If
+     there are more than one ATTRIBUTE_USER_PUBLIC_KEY attributes set
+     and ATTRIBUTE_USER_DIGITAL_SIGNATURE is also set, the digital
+     signature SHOULD be verifiable with the first set public key.
+
+     Length       Type       Value
+     variable     string     Public key/certificate type
+     variable     data       Public key/certificate data
+
+     The following public key/certificate types are defined:
+
+     ssh-rsa           SSH RSA public key [SSH-TRANS]
+     ssh-dss           SSH DSS public key [SSH-TRANS]
+     silc-rsa          SILC RSA public key [SILC1]
+     silc-dss          SILC DSS public key [SILC1]
+     pgp-sign-rsa      OpenPGP RSA certificate [RFC2440]
+     pgp-sign-dss      OpenPGP DSS certificate [RFC2440]
+     x509v3-sign-rsa   X.509 Version 3 RSA certificate [RFC2459]
+     x509v3-sign-dss   X.509 Version 3 DSS certificate [RFC2459]
+
+     Most of these public key/certificate types are equivalent to
+     the types specified for SSH protocol [SSH-TRANS] and are expected
+     to be officially assigned by IANA.
+
+     The encoding of the public key/certificate data in the attribute
+     is done in the manner defined in their respective definitions.
+
+     Note that these public keys are intended for signing.  Some
+     certificates may have a key usage restrictions and same key cannot
+     be used for both encryption and signing.  Therefore, the name
+     of the certificate type indicates if they are intended for 
+     signing only.
+
+
+13   ATTRIBUTE_SERVER_PUBLIC_KEY
+
+     This attribute includes a third party server or authority public
+     key or CA certificate and MUST be present if the attribute
+     ATTRIBUTE_SERVER_DIGITAL_SIGNATURE is also present.  The format
+     for this attribute is identical to the ATTRIBUTE_USER_PUBLIC_KEY 
+     attribute.  If there are more than one ATTRIBUTE_SERVER_PUBLIC_KEY
+     attributes set and ATTRIBUTE_SERVER_DIGITAL_SIGNATURE is also set,
+     the digital signature SHOULD be verifiable with the first set public
+     key.
+
+
+14   ATTRIBUTE_USER_DIGITAL_SIGNATURE
+
+     This attribute value includes digital signature of all Attribute
+     Payloads except this attribute.  This signature can be provided by
+     the user.  This attribute SHOULD be last attribute provided in the 
+     reply so that it is easier for the receiver to compute the signature 
+     data to be verified.  The format and encoding of this attribute
+     depends on the public key or certificate used to produce the
+     signature.  See the ATTRIBUTE_USER_PUBLIC_KEY for all public keys
+     and certificates that can be used to produce a signature.
+
+     Length       Type       Value
+     variable     data       Digital signature data
+
+     The encodings are as follows per public key/certificate type:
+
+     ssh-rsa and ssh-dss                   Defined in [SSH-TRANS]
+     silc-rsa and silc-dss                 Defined in [SILC1]
+     pgp-sign-rsa and pgp-sign-dss         Defined in [RFC2440]
+     x509v3-sign-rsa and x509v3-sign-dss   Defined in [PKCS7]
+
+     The procedure producing the signature and encoding it are done
+     in the manner defined in their respective definitions, see the
+     provided references.  Also the hash function used with the
+     signature procedure is defined by the public key/certificate type.
+
+
+15   ATTRIBUTE_SERVER_DIGITAL_SIGNATURE
+
+     This attribute value includes digital signature of all Attribute
+     Payloads except this attribute, but including the attribute
+     ATTRIBUTE_USER_DIGITAL_SIGNATURE.  This signature can be provided
+     by a third party server or an authority which has verified the
+     information provided by the user.  How it verifies this information
+     is out of scope of this document, however it may base its
+     information to a previous registration information and current
+     online status of the user in a service.  This attribute SHOULD be 
+     last when provided, so that it is easier for the receiver to
+     compute the signature data to be verified.  The format for this
+     attribute is identical to the ATTRIBUTE_USER_DIGITAL_SIGNATURE
+     attribute.
+.in 3
+
+
+.ti 0
+3 Security Considerations
+
+The use of these attributes dictates whether the attributes need to
+be secured or not.  However, as the attributes are considered to provide
+accurate status information about specific user, it is suggested that
+the attributes would be secured.  The attributes should be digitally
+signed whenever it is possible.  Attributes can also be encrypted
+if it is provided by the protocol using the attributes.  A third party,
+like a server in the network, could also verify the information and provide
+digital signature in case the information is accurate.
+
+Even though the attributes would be digitally signed by the sender of
+the attributes, the information contained in the attribute may still
+be incorrect.  The third party server should not apply digital signature
+unless it can verify every attribute.  The receiver of the attributes
+should also not trust that the information in fact is correct.
+
+However, it is possible that the context where these attributes are used
+the attributes are provided by a party that can provide the accurate
+information.  For example a server in the network could reply to the
+attributes on behalf of the actual user for some of the attributes.
+
+
+.ti 0
+4 References 
+
+[RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
+             Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 2279, January 1998.
+
+[RFC2425]    Howes, T., et al, "A MIME Content-Type for Directory
+             Information", RFC 2425, September 1998.
+
+[RFC2426]    Dawson, F., et al, "vCard MIME Directory Profile",
+             RFC 2426, September 1998.
+
+[SILC1]      Riikonen, P., "Secure Internet Live Conferencing (SILC),
+             Protocol Specification", Internet Draft, May 2002.
+
+[RFC2440]    Callas, J., et al, "OpenPGP Message Format", RFC 2440,
+             November 1998.
+
+[RFC2459]    Housley, R., et al, "Internet X.509 Public Key 
+             Infrastructure, Certificate and CRL Profile", RFC 2459,
+             January 1999.
+
+[SSH-TRANS]  Ylonen, T., et al, "SSH Transport Layer Protocol", 
+             Internet Draft.
+
+[PKCS7]      Kalinski, B., "PKCS #7: Cryptographic Message Syntax,
+             Version 1.5", RFC 2315, March 1998.
+
+
+
+
+.ti 0
+5 Author's Address
+
+Pekka Riikonen
+Snellmaninkatu 34 A 15
+70100 Kuopio
+Finland
+
+EMail: priikone@iki.fi
+
+
+.ti 0
+6 Full Copyright Statement
+
+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.
+
index 84e9197907b67b09a82afea17526405f7c5b6c4b..25da42b729d4a5ed37ff80387197406c649f616f 100644 (file)
@@ -8,7 +8,7 @@
 .ds RF FORMFEED[Page %]
 .ds CF
 .ds LH Internet Draft
-.ds RH 12 August 2003
+.ds RH 11 February 2004
 .ds CH
 .na
 .hy 0
@@ -16,8 +16,8 @@
 .nf
 Network Working Group                                        P. Riikonen
 Internet-Draft
-draft-riikonen-silc-commands-06.txt                       12 August 2003
-Expires: 12 February 2004
+draft-riikonen-silc-commands-06.txt                     11 February 2004
+Expires: 11 August 2004
 
 .in 3
 
@@ -76,13 +76,13 @@ Table of Contents
   2.1 SILC Commands Syntax ......................................  4
   2.2 SILC Command Argument Idioms ..............................  4
   2.3 SILC Commands List ........................................  5
-  2.4 SILC Command Status Payload ............................... 42
-3 SILC Status Types ............................................. 43
-4 Security Considerations ....................................... 50
-5 References .................................................... 50
-6 Author's Address .............................................. 51
-Appendix A ...................................................... 51
-Full Copyright Statement ........................................ 53
+  2.4 SILC Command Status Payload ............................... 43
+3 SILC Status Types ............................................. 44
+4 Security Considerations ....................................... 51
+5 References .................................................... 51
+6 Author's Address .............................................. 52
+Appendix A ...................................................... 52
+Full Copyright Statement ........................................ 54
 
 
 .ti 0
@@ -213,10 +213,9 @@ ID, length of the ID and the actual ID data.  This way variable length
 ID's can be sent as arguments.
 
 All passphrases that may be sent in commands as arguments MUST be
-UTF-8 [RFC2279] encoded.  All strings, with exeption of nicknames and
-channel names [SILC1], are UTF-8 encoded.  This includes strings like
-algorithm names, quit, kick and kill messages, service identifiers and
-others.
+UTF-8 [RFC3629] encoded.  All strings sent as arguments in command and
+command reply are also UTF-8 encoded, unless otherwise defined.  See
+the [SILC1] for general UTF-8 definition in SILC protocol.
 
 All public keys and certificates that are sent as arguments are actually
 Public Key Payloads [SILC2].  This way it is possible to send different
@@ -260,29 +259,35 @@ List of all defined commands in SILC follows.
 
         It is also possible to search the user by Client ID.  If the
         <Client ID> is provided server MUST use it as the search value
-        instead of the <nickname>.  One of the arguments MUST be given.
-        It is also possible to define multiple Client ID's to search
-        multiple users sending only one WHOIS command.  In this case the
-        Client ID's are appended as normal arguments.
+        instead of the <nickname>.  It is also possible to define multiple
+        Client ID's to search multiple users sending only one WHOIS
+        command.  In this case the Client ID's are appended as normal
+        arguments.
+
+        The <Requested Attributes> is defined in [ATTRS] and can be used
+        to request various information about the client.  See Appendix A
+        for definition of using these attributes in SILC.  If neither the
+        <nickname> or <Client ID> arguments are present but the attributes
+        are, the server MUST use the attributes to do the searching.  If
+        none of the arguments, <nickname>, <Client ID> and <Requested
+        Attributes> are present, error MUST be retuned.  Server MAY
+        use the <Requested Attributes> to narrow down the search if they
+        present at any time.
 
         To prevent miss-use of this command wildcards in the nickname
         or in the server name are not permitted.  It is not allowed
         to request all users on some server.  The WHOIS requests MUST
         be based on explicit nickname request.
 
-        The WHOIS request MUST be always sent to the router by server
-        so that all users are searched.  However, the server still MUST
-        search its locally connected clients.  The router MUST send
+        The WHOIS request MUST be always sent to the router by normal
+        server so that all users are searched.  However, the server still
+        MUST search its locally connected clients.  The router MUST send
         this command to the server which owns the requested client, if
         the router is unable to provide all mandatory information about
         the client.  That server MUST reply to the command.  Server MUST
         NOT send whois replies to the client until it has received the
         reply from its router.
 
-        The <Requested Attributes> is defined in [ATTRS] and can be used
-        to request various information about the client.  See Appendix A
-        for definition of using these attributes in SILC.
-
         Reply messages to the command:
 
         Max Arguments:  11
@@ -483,9 +488,8 @@ List of all defined commands in SILC follows.
             Arguments:  (1) <nickname>
 
         Set/change nickname.  This command is used to set nickname for
-        user.  Nickname MUST NOT include any whitespaces (` '),
-        non-printable characters, commas (`,'), '@', '!' or any wildcard
-        characters.
+        user.  See [SILC1] for definition of correctly formatted
+        nickname.
 
         When nickname is changed new Client ID is generated.  Server MUST
         distribute SILC_NOTIFY_TYPE_NICK_CHANGE to local clients on the
@@ -926,10 +930,8 @@ List of all defined commands in SILC follows.
         created.  If server is normal server this command MUST be sent
         to router which will create the channel.  The channel MAY be
         protected with passphrase.  If this is the case the passphrase
-        MUST be sent along the join command.
-
-        The name of the <channel> MUST NOT include any spaces (` '),
-        non-printable characters, commas (`,') or any wildcard characters.
+        MUST be sent along the join command.  See the [SILC1] for
+        definition of correctly formatted channel name, <channel>.
 
         The second argument <Client ID> is the Client ID of the client
         which is joining to the client.  When client sends this command
@@ -995,7 +997,7 @@ List of all defined commands in SILC follows.
 
         Reply messages to the command:
 
-        Max Arguments:  16
+        Max Arguments:  17
             Arguments:  (1) <Status Payload>        (2) <channel>
                         (3) <Channel ID>            (4) <Client ID>
                         (5) <channel mode mask>     (6) <created>
@@ -1004,6 +1006,7 @@ List of all defined commands in SILC follows.
                         (11) [<hmac>]               (12) <list count>
                         (13) <Client ID list>       (14) <client mode list>
                         (15) [<founder pubkey>]     (16) [<channel pubkeys>]
+                        (17) [<user limit>]
 
         This command replies with the channel name requested by the
         client, channel ID of the channel and topic of the channel
@@ -1012,6 +1015,7 @@ List of all defined commands in SILC follows.
         which tells all the modes set on the channel.  If the channel
         is created the mode mask is zero (0) and <created> is 0x01.
         If ban mask and/or invite list is set they are sent as well.
+        The <user limit> is the user limit on the channel, if one is set.
 
         The <list count>, <Client ID list> and <client mode list> are
         the clients currently on the channel and their modes on the
@@ -1478,22 +1482,23 @@ List of all defined commands in SILC follows.
         to all clients on the channel by sending the notify type
         SILC_NOTIFY_TYPE_CMODE_CHANGE.  The notify type MUST also be sent
         to the server's primary router.  If the <channel mode mask> was
-        not provided this command returns the mode mask, founder key
-        and channel public key list to the client.
+        not provided this command returns the mode mask, founder key,
+        channel public key list and the current user limit to the client.
 
         Reply messages to the command:
 
-        Max Arguments:  5
+        Max Arguments:  6
             Arguments:  (1) <Status Payload>    (2) <Channel ID>
                         (3) <channel mode mask> (4) [<founder pubkey>]
-                        (5) [<channel pubkeys>]
+                        (5) [<channel pubkeys>] (6) [<user limit>]
 
         This command replies with the changed channel mode mask that
         client MUST keep locally.  It may also return the channel
         founder's public key if it is set.  It may also return list of
         channel public keys when the list was altered.  The <channel
         pubkeys> is Argument List Payload and each argument includes
-        one public key.
+        one public key.  The <user limit> is the current user limit
+        on the channel, if one is set.
 
         Status messages:
 
@@ -1784,9 +1789,9 @@ List of all defined commands in SILC follows.
 
    22   SILC_COMMAND_WATCH
 
-        Max Arguments:  3
+        Max Arguments:  4
             Arguments:  (1) <Client ID>       (2) [<add nickname>]
-                        (3) [<del nickname>]
+                        (3) [<del nickname>]  (4) [<public key>]
 
         This command is used to set up a watch for <add nickname>
         nickname.  When a user in the network appears with the
@@ -1798,15 +1803,27 @@ List of all defined commands in SILC follows.
 
         The <del nickname> is a nickname that has been previously
         added to watch list and is now removed from it.  Notifications
-        for that nickname will not be delivered anymore.
+        for that nickname will not be delivered anymore.  The nickname
+        set to watch MUST NOT include any wildcards.  Note also that a
+        nickname may match several users since nicknames are not unique.
+        Implementations MAY set limits for how many nicknames client
+        can watch.
+
+        OPTIONALLY this command may also be set to watch clients' actions
+        in the network using their public key or certificate.  The
+        <public key> MAY be present, and it is an Argument List Payload
+        where each argument is a Public Key Payload including public key
+        to be added or removed from the watch list.  To To add a public
+        key to watch list the argument type is 0x00, and the argument is
+        the public key.  To remove a public key from watch list list the
+        argument type is 0x01, and the argument is the public key to be
+        removed from the list.  An implementation MAY limit the number of
+        public keys that can be set on the watch list.  Implementation MAY
+        add and remove multiple public keys at the same time by including
+        multiple arguments to the <public key> Argument List Payload.
 
         The <Client ID> is the Client ID of the sender of this command.
 
-        The nickname set to watch MUST NOT include any wildcards.
-        Note also that a nickname may match several users since
-        nicknames are not unique.  Implementations MAY set limits
-        for how many nicknames client can watch.
-
         When normal server receives this command from client it
         MUST send it to its router.  Router will process the command
         and actually keeps the watch list.
@@ -1998,7 +2015,7 @@ List of all defined commands in SILC follows.
         remote service.  The authentication to a service may be based
         on previous agreement with the requester and the service
         provider.  The command MAY also take additional service
-        specific arguments.  The <service name> is UTF-8 string.
+        specific arguments.
 
         This document does not specify any services.  How the services
         are configured and put available in a server is also out of
@@ -2518,8 +2535,8 @@ security of this protocol.
 [RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.
 
-[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
-             10646", RFC 2279, January 1998.
+[RFC3629]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 3629, November 2003.
 
 [ATTRS]      Riikonen, P., "User Online Presence and Information
              Attributes", Internet Draft, May 2002.
diff --git a/doc/draft-riikonen-silc-flags-payloads-04.nroff b/doc/draft-riikonen-silc-flags-payloads-04.nroff
new file mode 100644 (file)
index 0000000..3aada3c
--- /dev/null
@@ -0,0 +1,522 @@
+.pl 10.0i
+.po 0
+.ll 7.2i
+.lt 7.2i
+.nr LL 7.2i
+.nr LT 7.2i
+.ds LF Riikonen
+.ds RF FORMFEED[Page %]
+.ds CF
+.ds LH Internet Draft
+.ds RH 2 December 2003
+.ds CH
+.na
+.hy 0
+.in 0
+.nf
+Network Working Group                                        P. Riikonen
+Internet-Draft
+draft-riikonen-flags-payloads-04.txt                     2 December 2003
+Expires: 2 June 2004
+
+.in 3
+
+.ce 2
+SILC Message Flag Payloads
+<draft-riikonen-flags-payloads-04.txt>
+
+.ti 0
+Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with
+all provisions of Section 10 of RFC 2026.  Internet-Drafts are
+working documents of the Internet Engineering Task Force (IETF), its
+areas, and its working groups.  Note that other groups may also
+distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time.  It is inappropriate to use Internet-Drafts as reference
+material or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html
+
+The distribution of this memo is unlimited.
+
+
+.ti 0
+Abstract
+
+This memo describes the data payloads associated with the SILC Message
+Flags, as defined in the SILC Packet Protocol specification [SILC2].  The
+purpose of the Message Flags is to augment the function of the Message
+Payload used to send both private and channel messages, by allowing the
+sender to tell the receiver what type of data the payload includes, and
+how the data should be processed.  Some of the Message Flags may define
+additional payloads to be associated with the flag, and this memo
+describes these payloads.
+
+
+
+
+
+
+
+
+.ti 0
+Table of Contents
+
+.nf
+1 Introduction ..................................................  2
+  1.1 Requirements Terminology ..................................  2
+2 SILC Message Flags ............................................  3
+3 SILC Message Flag Payloads ....................................  3
+  3.1 SILC_MESSAGE_FLAG_REQUEST .................................  3
+  3.2 SILC_MESSAGE_FLAG_REPLY ...................................  4
+  3.3 SILC_MESSAGE_FLAG_SIGNED ..................................  4
+  3.4 SILC_MESSAGE_FLAG_DATA ....................................  7
+  3.5 SILC_MESSAGE_FLAG_ACK .....................................  8
+4 Security Considerations .......................................  9
+5 References ....................................................  9
+6 Author's Address .............................................. 10
+7 Full Copyright Statement ...................................... 10
+
+
+.ti 0
+1. Introduction
+
+The Secure Internet Live Conferencing [SILC1] supports sending binary
+messages between users in the network.  To make the data sending, and
+processing at the receiver's end as simple as possible the SILC defines
+Message Flags to the Message Payload [SILC2] that is used to send private
+and channel messages, which can help the receiver to decide how the data
+is encoded, and how it should be interpreted.  Some of the Message Flags
+may define additional payloads to be associated with the flag, but the
+[SILC2] does not define them.  This memo defines the payloads for those
+Message Flags that was marked to include additional payloads in [SILC2].
+
+By defining the payloads for the Message Flags the Message Payload
+can be augmented to support any kind of data, which can be easily
+interpreted at the receiver end.  For example, it would be possible to
+send audio stream, video stream, image files and HTML pages as messages,
+and the receiver can either choose to ignore the message or to process
+it, or to perhaps pass the message to some application for processing.
+Without specific payloads for Message Flags it is almost impossible for
+the receiver to interpret binary data from the payload.
+
+
+.ti 0
+1.1 Requirements Terminology
+
+The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED,
+MAY, and OPTIONAL, when they appear in this document, are to be
+interpreted as described in [RFC2119].
+
+
+
+
+.ti 0
+2 SILC Message Flags
+
+The Message Flags was added to the SILC protocol for the reason that SILC
+provides sending binary data as messages between users, and entities in
+the network, and interpreting pure binary data is almost impossible.
+With the Message Flags the purpose, the reason, and the method for how
+the message must be interpreted can be told to the recipient.  Other
+conferencing protocols which are usually ASCII based protocols do not have
+such problems since they do not generally support sending of binary data
+at all, or require specific encoding of the data before it can be sent
+over the network.
+
+The Message Payload in SILC can have flags that can augment the function
+of the payload.  The flags can tell for example that the message is a
+request, or a reply to an earlier received request.  They can tell that
+the message is some action that the sender is performing, or they can tell
+that the message is an auto reply, or that it is explicitly digitally
+signed by the sender.
+
+The problem of Message Flags is that the space for flags mask is only 16
+bits, so there is a limited number of flags available.  For this reason
+having a flag that defines a generic way of sending any kind of data as
+a message, and can be easily interpreted at the receiver's end is important.
+For this reason the flag SILC_MESSAGE_FLAG_DATA was added to the protocol
+which can represent any data.  This memo describe how this flag is used
+and how the associated payload is constructed and processed.  This memo
+also describes payloads for all the other flags that can have associated
+payloads.
+
+
+.ti 0
+3 SILC Message Flag Payloads
+
+The [SILC2] defines the flags which may have associated payloads.  This
+section will list these flags and define the payloads.
+
+
+.ti 0
+3.1 SILC_MESSAGE_FLAG_REQUEST
+
+Currently this flag can be used in the context of application specific,
+service specific or vendor specific requests, and the data payload type is
+dependent of this context.  Therefore, payload is not defined for this
+flag in this memo.  This flag may also be masked with some other flag in
+the message payload, including with some other flag that defines
+additional payload.
+
+
+
+
+.ti 0
+3.2 SILC_MESSAGE_FLAG_REPLY
+
+Currently this flag can be used in the context of application specific,
+service specific or vendor specific replies, and the data payload type is
+dependent of this context.  Therefore, payload is not defined for this
+flag in this memo.  This flag may also be masked with some other flag in
+the message payload, including with some other flag that defines
+additional payload.
+
+
+.ti 0
+3.3 SILC_MESSAGE_FLAG_SIGNED
+
+This flag is used to tell the recipient that the sent message is
+digitally signed by the sender, and that the recipient should verify
+the signature to verify the true authenticity of the received message.
+All message payloads in SILC provides message authentication code (MAC)
+which can be used to verify that the sender produced and sent the message.
+Even so, signing messages digitally can be used to verify the authenticity
+of the message when recipient trusts the sender and to provide
+non-repudiation.
+
+This flag defines a payload which is used to deliver the actual message,
+sender's public key and the digital signature.  The payload for
+SILC_MESSAGE_FLAG_SIGNED is as follows:
+
+(*) indicates that the field is not encrypted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                   Start of Message Payload                    ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                      Public Key Payload *                     ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     Signature Data Length *   |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                        Signature Data *                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                       Initial Vector *                        ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                              MAC *                            ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 1:  SILC_MESSAGE_FLAG_SIGNED Payload
+
+
+.in 6
+o Start of Message Payload (variable length) - This is the
+  start of the Message Payload without the IV and MAC fields,
+  since those fields are appended at the end of this payload.
+
+o Public Key Payload (variable length) - This includes the
+  Public Key Payload [SILC2] which can be used to deliver the
+  sender's public key (or certificate).  It also indicates the
+  type of the public key (or certificate) which the recipient
+  use to identify how the signature must be verified.  This
+  payload must always be present but it is not required to
+  include the public key data.  The Public Key Type field in
+  the Public Key Payload MUST be set to the correct type of
+  the key, even if the actual public key data is not included.
+  This field is not encrypted but is authenticated.
+
+o Signature Data Length (2 bytes) - Indicates the length of
+  the Signature Data field not including any other field.
+  This field is not encrypted but is authenticated.
+
+o Signature Data (variable length) - Includes the actual
+  signature data.  The signature computation and encoding
+  is key type specific.  See [SILC3] for all key types, and
+  their respective references for how to compute and encode
+  the signature.  This field is not encrypted but is
+  authenticated.
+
+o Initial Vector (variable length) - the IV of the Message
+  Payload as defined in [SILC2].  This field is not encrypted
+  but is authenticated.
+
+o MAC (variable length) - the MAC of the Message Payload as
+  defined in [SILC2].  The MAC is computed after encryption
+  and after signature computation.  All data in the Message
+  Payload and this payload, including the IV field are
+  included in the MAC computation.  This field is not
+  encrypted.
+.in 3
+
+How the data is processed before it is signed is key type specific.
+The actual data that to be signed MUST be the plaintext message
+payload before encryption.  The data to be signed is concatenation
+of the Start of Message Payload field and the Public Key Payload,
+in that order.  Any other fields are not included for signature data.
+Before signing, the data is always processed, usually hashed.  The
+hash function to be used is defined in the key type specific
+definitions.  See the key type specific references in [SILC3].
+
+If the public key of the sender is included in the payload the
+recipient SHOULD verify it before accepting the public key.  Recipient
+SHOULD verify the signature before accepting and caching the public key.
+With certificates the certificate verification may be done before
+verifying the signature.  If the signature verification fails the
+message should still be displayed.  The end user should also be
+notified about the result of the signature verification.
+
+To make the packet size smaller implementations may not want to
+include the actual public key in all signed messages.  Sending the
+public key in the first message is usually sufficient.  Subsequent
+messages may include empty Public Key Payload with an indication of
+the public key type.
+
+Implementations that do not support this flag can still process the
+message payload in normal manner.  These implementations merely parse
+the decrypted payload in normal manner and ignore the extra data in
+the payload.  They can do this by extracting the MAC and the IV from
+the end of the data buffer and thus ignoring the data between start of
+the Message Payload and the Initial Vector field.
+
+This flag MAY be masked with any other Message Flag including those that
+define additional payloads.  As long as the defined payload resides in
+the data area of the message payload this flag may be masked with the
+other flags.
+
+
+.ti 0
+3.4 SILC_MESSAGE_FLAG_DATA
+
+This flag is used to represent any data as a message in the way that it
+can be easily interpreted by the recipient.  This flag is used to send
+MIME objects as messages from the sender to the receiver.  The MIME as
+defined in [RFC2045], [RFC2046], [RFC2047], [RFC2048] and [RFC2049] is
+well established protocol for sending different kind of data with many
+applications and protocols.  It support dozens of different media types
+and encodings, and for this reason is ideal for sending data in SILC
+message payloads as well.
+
+When the receiver has checked that the message payload includes the
+SILC_MESSAGE_FLAG_DATA flag, it may then start parsing the MIME header.
+It would also be possible to pass the message to some application which
+can already interpret MIME objects.  If the receiver does not support the
+media type received in the MIME header, it SHOULD be treated as
+"application/octet-stream".  The receiver MAY also ignore and discard
+messages that it does not support.
+
+The MIME header MUST be at the start of the data area of the Message
+Payload.  The MIME header received in the data area of the payload SHOULD
+have the MIME-Version field at first and then Content-Type field.  The
+MIME-Version field is not required to be present in each body part of
+multipart entity.  Additionally the header MAY also include any other
+MIME compliant headers.  The character encoding for the MIME Header
+strings inside the message payload is US-ASCII, as defined in [RFC2045].
+The actual MIME object may define additional character sets or encodings
+for the data it delivers.
+
+Hence, the MIME Header in the message payload may be as follows:
+
+.in 8
+.nf
+MIME-Version: 1.0\\r\\n
+Content-Type: discrete/composite\\r\\n
+Content-Transfer-Encoding: binary\\r\\n
+\\r\\n
+.in 3
+
+The Content-Transfer-Encoding field behaves as defined in [RFC2045] and
+defines the encoding of the data in the MIME object.  The preferred data
+encoding with SILC is "binary".  However, many MIME media types defines
+their preferred encoding and they may be used if binary encoding is not
+suitable.
+
+When sending large amounts of traffic or large files as MIME objects the
+limits of the SILC Packet needs to be taken into consideration.  The
+maximum length of SILC Packet is 2^16 bytes, and larger messages would
+need to be fragmented.  MIME provides way of fragmenting and reassembling
+messages, and it is to be done with SILC as defined in [RFC2046].  The
+MIME fragmentation is defined for gateway usage, but in case of SILC the
+sender (for example, a client) may also start sending fragmented MIME
+objects.
+
+This flag SHOULD NOT be masked with some other Message Flag that defines
+payloads for message data.  Generally this sort of setting would be
+impossible for the receiver to interpret.  However, flags that does not
+define any specific payloads MAY be masked with this flag as well.  For
+example, this flag could be masked also with SILC_MESSAGE_FLAG_REQUEST flag.
+It also can be masked with SILC_MESSAGE_FLAG_SIGNED flag since it does not
+define data specific payload.
+
+
+.ti 0
+3.5 SILC_MESSAGE_FLAG_ACK
+
+This flag is used to send acknowledgement messages.  When sender of a
+message requires the recipient to acknowledge the received message, the
+sender MUST set the SILC_MESSAGE_FLAG_ACK and MUST NOT set the
+SILC_MESSAGE_FLAG_NOREPLY.  When a message with this flag set is received
+an acknowledgement message MUST be sent back.  In the acknowledgement
+message the sender MUST set the SILC_MESSAGE_FLAG_ACK,
+SILC_MESSAGE_FLAG_AUTOREPLY and SILC_MESSAGE_FLAG_NOREPLY flags.  The
+receiver MUST NOT acknowledge the acknowledgement message.  This flag
+MUST NOT be used with channel messages, and MUST be ignored if received
+in a channel message.
+
+The construction of the acknowledgement reply message is normal Message
+Payload where the Message Data field includes a computed MAC of the
+original received Message Payload MAC.  Hence, the MAC is computed as
+follows:
+
+.in 8
+ack_mac = mac(key, MAC);
+.in 3
+
+Where the 'key' is the MAC key used to compute MACs for the Message
+Payload, and the 'MAC' is the MAC taken from the received Message Payload.
+The 'ack_mac' is placed in the Message Data field in a new Message
+Payload, and the payload is encrypted in normal manner.  After this the
+message is sent back to the original sender of the message.
+
+The receiver of the acknowledgement reply message SHOULD verify the MAC
+from the Message Data field to assure that acknowledgement was received to
+an earlier sent message.  Implementation needs to keep the old message
+MACs stored until acknowledgement is received.  It is left for
+implementation to decide any possible retransmission strategy if
+acknowledgement messages are not received.
+
+
+.ti 0
+4 Security Considerations
+
+In case of SILC_MESSAGE_FLAG_DATA the implementors should pay special
+attention to the security implications of any media type that can cause
+the remote execution of any actions in the receiver's environment.  The
+[RFC2046] and [RFC2048] discusses more MIME specific security
+considerations.  Even though SILC provides secured messages, in case of
+MIME which can be used to transfer files and documents which are stored in
+the receiver's local environment, securing separately the MIME object may
+be desired.  For example, augmenting the MIME support in SILC messages to
+support S/MIME may be desired in some implementations.
+
+
+.ti 0
+5 References
+
+[SILC1]      Riikonen, P., "Secure Internet Live Conferencing (SILC),
+             Protocol Specification", Internet Draft, June 2003.
+
+[SILC2]      Riikonen, P., "SILC Packet Protocol", Internet Draft,
+             June 2003.
+
+[SILC3]      Riikonen, P., "SILC Key Exchange and Authentication
+             Protocols", Internet Draft, June 2003.
+
+[RFC2045]    Freed, N., et al., "Multipurpose Internet Mail Extensions
+             (MIME) Part One: Format of Internet Message Bodies",
+             Standards Track, RFC 2045, November 1996.
+
+[RFC2046]    Freed, N., et al., "Multipurpose Internet Mail Extensions
+             (MIME) Part Two: Media Types", Standards Track, RFC 2045,
+             November 1996.
+
+[RFC2047]    Moore K., "MIME (Multipurpose Internet Mail Extensions)
+             Part Three: Message Header Extensions for Non-ASCII Text"
+             Standards Track, RFC 2047, November 1996.
+
+[RFC2048]    Freed, N., et al., "Multipurpose Internet Mail Extensions
+             (MIME) Part Four: Registration Procedures", Standards
+             Track, RFC 2048, November 1996.
+
+[RFC2049]    Freed, N., et al., "Multipurpose Internet Mail Extensions
+             (MIME) Part Five: Conformance Criteria and Examples",
+             Standards Track, RFC 2049, November 1996.
+
+[RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
+             Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+
+
+.ti 0
+6 Author's Address
+
+Pekka Riikonen
+Snellmaninkatu 34 A 15
+70100 Kuopio
+Finland
+
+EMail: priikone@iki.fi
+
+
+
+.ti 0
+7 Full Copyright Statement
+
+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.
diff --git a/doc/draft-riikonen-silc-ke-auth-08.nroff b/doc/draft-riikonen-silc-ke-auth-08.nroff
new file mode 100644 (file)
index 0000000..22638c3
--- /dev/null
@@ -0,0 +1,1180 @@
+.pl 10.0i
+.po 0
+.ll 7.2i
+.lt 7.2i
+.nr LL 7.2i
+.nr LT 7.2i
+.ds LF Riikonen
+.ds RF FORMFEED[Page %]
+.ds CF
+.ds LH Internet-Draft
+.ds RH 2 February 2003
+.ds CH
+.na
+.hy 0
+.in 0
+.nf
+Network Working Group                                        P. Riikonen
+Internet-Draft
+draft-riikonen-silc-ke-auth-08.txt                       2 February 2004
+Expires: 2 August 2004
+
+.in 3
+
+.ce 2
+SILC Key Exchange and Authentication Protocols
+<draft-riikonen-silc-ke-auth-08.txt>
+
+.ti 0
+Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with
+all provisions of Section 10 of RFC 2026.  Internet-Drafts are
+working documents of the Internet Engineering Task Force (IETF), its
+areas, and its working groups.  Note that other groups may also
+distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time.  It is inappropriate to use Internet-Drafts as reference
+material or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html
+
+The distribution of this memo is unlimited.
+
+
+.ti 0
+Abstract
+
+This memo describes two protocols used in the Secure Internet Live
+Conferencing (SILC) protocol, specified in the Secure Internet Live
+Conferencing, Protocol Specification [SILC1].  The SILC Key Exchange
+(SKE) protocol provides secure key exchange between two parties
+resulting into shared secret key material.  The protocol is based
+on Diffie-Hellman key exchange algorithm and its functionality is
+derived from several key exchange protocols.
+
+The second protocol, SILC Connection Authentication protocol provides
+user level authentication used when creating connections in SILC
+network.  The protocol is transparent to the authentication data
+which means that it can be used to authenticate the connection with, for
+example, passphrase (pre-shared secret) or public key (and certificate)
+based on digital signatures.
+
+
+
+.ti 0
+Table of Contents
+
+.nf
+1 Introduction ..................................................  2
+  1.1 Requirements Terminology ..................................  3
+2 SILC Key Exchange Protocol ....................................  3
+  2.1 Key Exchange Payloads .....................................  4
+      2.1.1 Key Exchange Start Payload ..........................  4
+      2.1.2 Key Exchange Payload ................................  8
+  2.2 Key Exchange Procedure .................................... 11
+  2.3 Processing the Key Material ............................... 12
+  2.4 SILC Key Exchange Groups .................................. 14
+      2.4.1 diffie-hellman-group1 ............................... 14
+      2.4.2 diffie-hellman-group2 ............................... 15
+      2.4.3 diffie-hellman-group3 ............................... 15
+  2.5 Key Exchange Status Types ................................. 16
+3 SILC Connection Authentication Protocol ....................... 17
+  3.1 Connection Auth Payload ................................... 18
+  3.2 Connection Authentication Types ........................... 19
+      3.2.1 Passphrase Authentication ........................... 19
+      3.2.2 Public Key Authentication ........................... 20
+  3.3 Connection Authentication Status Types .................... 21
+4 Security Considerations ....................................... 21
+5 References .................................................... 21
+6 Author's Address .............................................. 23
+7 Full Copyright Statement ...................................... 23
+
+
+.ti 0
+List of Figures
+
+.nf
+Figure 1:  Key Exchange Start Payload
+Figure 2:  Key Exchange Payload
+Figure 3:  Connection Auth Payload
+
+
+.ti 0
+1 Introduction
+
+This memo describes two protocols used in the Secure Internet Live
+Conferencing (SILC) protocol specified in the Secure Internet Live
+Conferencing, Protocol Specification [SILC1].  The SILC Key Exchange
+(SKE) protocol provides secure key exchange between two parties
+resulting into shared secret key material.  The protocol is based on
+Diffie-Hellman key exchange algorithm and its functionality is derived
+from several key exchange protocols, such as SSH2 Key Exchange protocol,
+Station-To-Station (STS) protocol and the OAKLEY Key Determination
+protocol [OAKLEY].
+
+The second protocol, SILC Connection Authentication protocol provides
+user level authentication used when creating connections in SILC
+network.  The protocol is transparent to the authentication data which
+means that it can be used to authenticate the connection with, for example,
+passphrase (pre-shared secret) or public key (and certificate) based
+on digital signatures.
+
+The basis of secure SILC session requires strong and secure key exchange
+protocol and authentication.  The authentication protocol is secured and
+no authentication data is ever sent in the network without encrypting
+and authenticating it first.  Thus, authentication protocol may be used
+only after the key exchange protocol has been successfully completed.
+
+This document constantly refers to other SILC protocol specifications
+that should be read to be able to fully understand the functionality
+and purpose of these protocols.  The most important references are
+the Secure Internet Live Conferencing, Protocol Specification [SILC1]
+and the SILC Packet Protocol [SILC2].
+
+The protocol is intended to be used with the SILC protocol thus it
+does not define own framework that could be used.  The framework is
+provided by the SILC protocol.
+
+
+.ti 0
+1.1 Requirements Terminology
+
+The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED,
+MAY, and OPTIONAL, when they appear in this document, are to be
+interpreted as described in [RFC2119].
+
+
+.ti 0
+2 SILC Key Exchange Protocol
+
+SILC Key Exchange Protocol (SKE) is used to exchange shared secret
+material used to secure the communication channel.  The protocol use
+Diffie-Hellman key exchange algorithm and its functionality is derived
+from several key exchange protocols, such as SSH2 Key Exchange protocol,
+Station-To-Station (STS) protocol and the OAKLEY Key Determination
+protocol [OAKLEY].  The protocol does not claim any conformance
+to any of these protocols, they were only used as a reference when
+designing this protocol.  The protocol can mutually authenticate the
+negotiating parties during the key exchange.
+
+The purpose of SILC Key Exchange protocol is to create session keys to
+be used in current SILC session.  The keys are valid only for some period
+of time (usually an hour) or at most until the session ends.  These keys
+are used to protect packets traveling between the two entities.
+Usually all traffic is secured with the key material derived from this
+protocol.
+
+The Diffie-Hellman implementation used in the SILC SHOULD be compliant
+to the PKCS #3.
+
+
+.ti 0
+2.1 Key Exchange Payloads
+
+During the key exchange procedure public data is sent between initiator
+and responder.  This data is later used in the key exchange procedure.
+There are several payloads used in the key exchange.  As for all SILC
+packets, SILC Packet Header, described in [SILC2], is at the beginning
+of all packets sent in during this protocol.  All the fields in the
+following payloads are in MSB (most significant byte first) order.
+Following descriptions of these payloads.
+
+
+.ti 0
+2.1.1 Key Exchange Start Payload
+
+The key exchange between two entities MUST be started by sending the
+SILC_PACKET_KEY_EXCHANGE packet containing Key Exchange Start Payload.
+Initiator sends the Key Exchange Start Payload to the responder filled
+with all security properties it supports.  The responder then checks
+whether it supports the security properties.
+
+It then sends a Key Exchange Start Payload to the initiator filled with
+security properties it selected from the original payload.  The payload
+sent by responder MUST include only one chosen property per list.  The
+character encoding for the security property values as defined in [SILC1]
+SHOULD be UTF-8 [RFC2279] in Key Exchange Start Payload.
+
+The Key Exchange Start Payload is used to tell connecting entities what
+security properties and algorithms should be used in the communication.
+The Key Exchange Start Payload is sent only once per session.  Even if
+the PFS (Perfect Forward Secrecy) flag is set the Key Exchange Start
+Payload is not re-sent.  When PFS is desired the Key Exchange Payloads
+are sent to negotiate new key material.  The procedure is equivalent to
+the very first negotiation except that the Key Exchange Start Payload
+is not sent.
+
+As this payload is used only with the very first key exchange the payload
+is never encrypted, as there are no keys to encrypt it with.
+
+A cookie is also sent in this payload.  A cookie is used to randomize the
+payload so that none of the key exchange parties can determine this
+payload before the key exchange procedure starts.  The cookie MUST be
+returned to the original sender unmodified by the responder.
+
+Following diagram represents the Key Exchange Start Payload.  The lists
+mentioned below are always comma (`,') separated and the list MUST NOT
+include white spaces (` ').
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|   RESERVED    |     Flags     |         Payload Length        |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
++                                                               +
+|                                                               |
++                            Cookie                             +
+|                                                               |
++                                                               +
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     Version String Length     |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                         Version String                        ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|   Key Exchange Grp Length     |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                      Key Exchange Groups                      ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        PKCS Alg Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                         PKCS Algorithms                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     Encryption Alg Length     |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                      Encryption Algorithms                    ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Hash Alg Length         |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                         Hash Algorithms                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|         HMAC Length           |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                             HMACs                             ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|    Compression Alg Length     |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                     Compression Algorithms                    ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 1:  Key Exchange Start Payload
+
+
+.in 6
+o RESERVED (1 byte) - Reserved field.  Sender fills this with
+  zero (0) value.
+
+o Flags (1 byte) - Indicates flags to be used in the key
+  exchange.  Several flags can be set at once by ORing the
+  flags together.  The following flags are reserved for this
+  field:
+
+     No flags                 0x00
+
+       In this case the field is ignored.
+
+     IV Included              0x01
+
+       This flag is used to indicate that Initial Vector (IV)
+       in encryption will be included in the ciphertext
+       which the recipient must use in decryption.  The IV
+       MUST be set after the last ciphertext block.  With
+       this flag it is possible to use SILC protocol on
+       unreliable transport such as UDP/IP which may cause
+       packet reordering and packet losses.  By default,
+       this flag is not set and thus IV is not included
+       in the ciphertext.  Setting this flag increases the
+       ciphertext size by one ciphertext block.  Responder
+       MAY override this flag for the initiator.
+
+     PFS                      0x02
+
+       Perfect Forward Secrecy (PFS) to be used in the
+       key exchange protocol.  If not set, re-keying
+       is performed using the old key.  See the [SILC1]
+       for more information on this issue.  When PFS is
+       used, re-keying and creating new keys for any
+       particular purpose MUST cause new key exchange with
+       new Diffie-Hellman exponent values.  In this key
+       exchange only the Key Exchange Payload is sent and
+       the Key Exchange Start Payload MUST NOT be sent.
+       When doing PFS the Key Exchange Payloads are
+       encrypted with the old keys.
+
+     Mutual Authentication    0x04
+
+       Both of the parties will perform authentication
+       by providing signed data for the other party to
+       verify.  By default, only responder will provide
+       the signature data.  If this is set then the
+       initiator must also provide it.  Initiator MAY
+       set this but also responder MAY set this even if
+       initiator did not set it.
+
+     Rest of the flags are reserved for the future and
+     MUST NOT be set.
+
+o Payload Length (2 bytes) - Length of the entire Key Exchange
+  Start payload, not including any other field.
+
+o Cookie (16 bytes) - Cookie that randomize this payload so
+  that each of the party cannot determine the payload before
+  hand.  This field MUST be present.
+
+o Version String Length (2 bytes) - The length of the Version
+  String field, not including any other field.
+
+o Version String (variable length) - Indicates the version of
+  the sender of this payload.  Initiator sets this when sending
+  the payload and responder sets this when it replies by sending
+  this payload.  See [SILC1] for definition for the version
+  string format.  This field MUST be present and include valid
+  version string.
+
+o Key Exchange Grp Length (2 bytes) - The length of the
+  key exchange group list, not including any other field.
+
+o Key Exchange Group (variable length) - The list of
+  key exchange groups.  See the section 2.4 SILC Key Exchange
+  Groups for definitions of these groups.  This field MUST
+  be present.
+
+o PKCS Alg Length (2 bytes) - The length of the PKCS algorithms
+  list, not including any other field.
+
+o PKCS Algorithms (variable length) - The list of PKCS
+  algorithms.  This field MUST be present.
+
+o Encryption Alg Length (2 bytes) - The length of the encryption
+  algorithms list, not including any other field.
+
+o Encryption Algorithms (variable length) - The list of
+  encryption algorithms.  This field MUST be present.
+
+o Hash Alg Length (2 bytes) - The length of the Hash algorithm
+  list, not including any other field.
+
+o Hash Algorithms (variable length) - The list of Hash
+  algorithms.  The hash algorithms are mainly used in the
+  SKE protocol.  This field MUST be present.
+
+o HMAC Length (2 bytes) - The length of the HMAC list, not
+  including any other field.
+
+o HMACs (variable length) - The list of HMACs.  The HMAC's
+  are used to compute the Message Authentication Code (MAC)
+  of the SILC packets.  This field MUST be present.
+
+o Compression Alg Length (2 bytes) - The length of the
+  compression algorithms list, not including any other field.
+
+o Compression Algorithms (variable length) - The list of
+  compression algorithms.  This field MAY be omitted.
+.in 3
+
+
+.ti 0
+2.1.2 Key Exchange Payload
+
+Key Exchange payload is used to deliver the public key (or certificate),
+the computed Diffie-Hellman public value and possibly signature data
+from one party to the other.  When initiator is using this payload
+and the Mutual Authentication flag is not set then the initiator MUST
+NOT provide the signature data.  If the flag is set then the initiator
+MUST provide the signature data so that the responder can verify it.
+
+The Mutual Authentication flag is usually used when a separate
+authentication protocol will not be executed for the initiator of the
+protocol.  This is case for example when the SKE is performed between
+two SILC clients.  In normal case, where client is connecting to a
+server, or server is connecting to a router the Mutual Authentication
+flag MAY be omitted.  However, if the connection authentication protocol
+for the connecting entity is not based on digital signatures (it is
+based on pre-shared key) then the Mutual Authentication flag SHOULD be
+enabled.  This way the connecting entity has to provide proof of
+possession of the private key for the public key it will provide in
+this protocol.
+
+When performing re-key with PFS selected this is the only payload that
+is sent in the SKE protocol.  The Key Exchange Start Payload MUST NOT
+be sent at all.  However, this payload does not have all the fields
+present.  In the re-key with PFS the public key and a possible signature
+data SHOULD NOT be present.  If they are present they MUST be ignored.
+The only field that is present is the Public Data that is used to create
+the new key material.  In the re-key the Mutual Authentication flag, that
+may be set in the initial negotiation, MUST also be ignored.
+
+This payload is sent inside SILC_PACKET_KEY_EXCHANGE_1 and inside
+SILC_PACKET_KEY_EXCHANGE_2 packet types.  The initiator uses the
+SILC_PACKET_KEY_EXCHANGE_1 and the responder the latter.
+
+The following diagram represent the Key Exchange Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Public Key Length       |        Public Key Type        |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~            Public Key of the party (or certificate)           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Public Data Length      |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                          Public Data                          ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Signature Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                        Signature Data                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 2:  Key Exchange Payload
+
+
+.in 6
+o Public Key Length (2 bytes) - The length of the Public Key
+  (or certificate) field, not including any other field.
+
+o Public Key Type (2 bytes) - The public key (or certificate)
+  type.  This field indicates the type of the public key in
+  the packet.  Following types are defined:
+
+     1    SILC style public key (mandatory)
+     2    SSH2 style public key (optional)
+     3    X.509 Version 3 certificate (optional)
+     4    OpenPGP certificate (optional)
+     5    SPKI certificate (optional)
+
+  The only required type to support is type number 1.  See
+  [SILC1] for the SILC public key specification.  See
+  SSH2 public key specification in [SSH-TRANS].  See X.509v3
+  certificate specification in [PKIX-Part1].  See OpenPGP
+  certificate specification in [PGP].  See SPKI certificate
+  specification in [SPKI].  If this field includes zero (0)
+  or unsupported type number the protocol MUST be aborted
+  sending SILC_PACKET_FAILURE message and the connection SHOULD
+  be closed immediately.
+
+o Public Key (or certificate) (variable length) - The
+  public key or certificate of the party.  This public key
+  is used to verify the digital signature.  The public key
+  or certificate in this field is encoded in the manner as
+  defined in their respective definitions; see previous field.
+
+o Public Data Length (2 bytes) - The length of the Public Data
+  field, not including any other field.
+
+o Public Data (variable length) - The public data to be
+  sent to the receiver (computed Diffie-Hellman public values).
+  See section 2.2 Key Exchange Procedure for detailed description
+  how this field is computed.  This field is MP integer and is
+  encoded as defined in [SILC1].
+
+o Signature Length (2 bytes) - The length of the signature,
+  not including any other field.
+
+o Signature Data (variable length) - The signature signed
+  by the sender.  The receiver of this signature MUST
+  verify it.  The verification is done using the sender's
+  public key.  See section 2.2 Key Exchange Procedure for
+  detailed description how to produce the signature.  If
+  the Mutual Authentication flag is not set then initiator
+  MUST NOT provide this field and the Signature Length field
+  MUST be set to zero (0) value.  If the flag is set then
+  also the initiator MUST provide this field.  The responder
+  always MUST provide this field.  The encoding for signature
+  is defined in [SILC1].
+.in 3
+
+
+
+.ti 0
+2.2 Key Exchange Procedure
+
+The key exchange begins by sending SILC_PACKET_KEY_EXCHANGE packet with
+Key Exchange Start Payload to select the security properties to be used
+in the key exchange and later in the communication.
+
+After Key Exchange Start Payload has been processed by both of the
+parties the protocol proceeds as follows:
+
+
+Setup:  p is a large and public safe prime.  This is one of the
+        Diffie Hellman groups.  q is order of subgroup (largest
+        prime factor of p).  g is a generator and is defined
+        along with the Diffie Hellman group.
+
+    1.  Initiator generates a random number x, where 1 < x < q,
+        and computes e = g ^ x mod p.  The result e is then
+        encoded into Key Exchange Payload, with the public key
+        (or certificate) and sent to the responder.
+
+        If the Mutual Authentication flag is set then initiator
+        MUST also produce signature data SIGN_i which the responder
+        will verify.  The initiator MUST compute a hash value
+        HASH_i = hash(Initiator's Key Exchange Start Payload |
+        public key (or certificate) | e).  The '|' stands for
+        concatenation.  It then signs the HASH_i value with its
+        private key resulting a signature SIGN_i.
+
+    2.  Responder generates a random number y, where 1 < y < q,
+        and computes f = g ^ y mod p.  It then computes the
+        shared secret KEY = e ^ y mod p, and, a hash value
+        HASH = hash(Initiator's Key Exchange Start Payload |
+        public key (or certificate) | Initiator's public key
+        (or certificate) | e | f | KEY).  It then signs
+        the HASH value with its private key resulting a signature
+        SIGN.
+
+        It then encodes its public key (or certificate), f and
+        SIGN into Key Exchange Payload and sends it to the
+        initiator.
+
+        If the Mutual Authentication flag is set then the responder
+        SHOULD verify that the public key provided in the payload
+        is authentic, or if certificates are used it verifies the
+        certificate.  The responder MAY accept the public key without
+        verifying it, however, doing so may result to insecure key
+        exchange (accepting the public key without verifying may be
+        desirable for practical reasons on many environments.  For
+        long term use this is never desirable, in which case
+        certificates would be the preferred method to use).  It then
+        computes the HASH_i value the same way initiator did in the
+        phase 1.  It then verifies the signature SIGN_i from the
+        payload with the hash value HASH_i using the received public
+        key.
+
+    3.  Initiator verifies that the public key provided in
+        the payload is authentic, or if certificates are used
+        it verifies the certificate.  The initiator MAY accept
+        the public key without verifying it, however, doing
+        so may result to insecure key exchange (accepting the
+        public key without verifying may be desirable for
+        practical reasons on many environments.  For long term
+        use this is never desirable, in which case certificates
+        would be the preferred method to use).
+
+        Initiator then computes the shared secret KEY =
+        f ^ x mod p, and, a hash value HASH in the same way as
+        responder did in phase 2.  It then verifies the
+        signature SIGN from the payload with the hash value
+        HASH using the received public key.
+
+
+If any of these phases is to fail the SILC_PACKET_FAILURE MUST be sent
+to indicate that the key exchange protocol has failed, and the connection
+SHOULD be closed immediately.  Any other packets MUST NOT be sent or
+accepted during the key exchange except the SILC_PACKET_KEY_EXCHANGE_*,
+SILC_PACKET_FAILURE and SILC_PACKET_SUCCESS packets.
+
+The result of this protocol is a shared secret key material KEY and
+a hash value HASH.  The key material itself is not fit to be used as
+a key, it needs to be processed further to derive the actual keys to be
+used.  The key material is also used to produce other security parameters
+later used in the communication.  See section 2.3 Processing the Key
+Material for detailed description how to process the key material.
+
+If the Mutual Authentication flag was set the protocol produces also
+a hash value HASH_i.  This value, however, must be discarded.
+
+After the keys are processed the protocol is ended by sending the
+SILC_PACKET_SUCCESS packet.  Both entities send this packet to
+each other.  After this both parties MUST start using the new keys.
+
+
+.ti 0
+2.3 Processing the Key Material
+
+Key Exchange protocol produces secret shared key material KEY.  This
+key material is used to derive the actual keys used in the encryption
+of the communication channel.  The key material is also used to derive
+other security parameters used in the communication.  Key Exchange
+protocol produces a hash value HASH as well.
+
+The keys MUST be derived from the key material as follows:
+
+.in 6
+Sending Initial Vector (IV)     = hash(0x0 | KEY | HASH)
+Receiving Initial Vector (IV)   = hash(0x1 | KEY | HASH)
+Sending Encryption Key          = hash(0x2 | KEY | HASH)
+Receiving Encryption Key        = hash(0x3 | KEY | HASH)
+Sending HMAC Key                = hash(0x4 | KEY | HASH)
+Receiving HMAC Key              = hash(0x5 | KEY | HASH)
+.in 3
+
+
+The Initial Vector (IV) is used in the encryption when doing for
+example CBC mode.  As many bytes as needed are taken from the start of
+the hash output for IV.  Sending IV is for sending key and receiving IV
+is for receiving key.  For receiving party, the receiving IV is actually
+sender's sending IV, and, the sending IV is actually sender's receiving
+IV.  Initiator uses IV's as they are (sending IV for sending and
+receiving IV for receiving).
+
+The Encryption Keys are derived as well from the hash().  If the hash()
+output is too short for the encryption algorithm more key material MUST
+be produced in the following manner:
+
+.in 6
+K1 = hash(0x2 | KEY | HASH)
+K2 = hash(KEY | HASH | K1)
+K3 = hash(KEY | HASH | K1 | K2)  ...
+
+Sending Encryption Key = K1 | K2 | K3 ...
+
+
+K1 = hash(0x3 | KEY | HASH)
+K2 = hash(KEY | HASH | K1)
+K3 = hash(KEY | HASH | K1 | K2)  ...
+
+Receiving Encryption Key = K1 | K2 | K3 ...
+.in 3
+
+
+The key is distributed by hashing the previous hash with the original
+key material.  The final key is a concatenation of the hash values.
+For Receiving Encryption Key the procedure is equivalent.  Sending key
+is used only for encrypting data to be sent.  The receiving key is used
+only to decrypt received data.  For receiving party, the receive key is
+actually sender's sending key, and, the sending key is actually sender's
+receiving key.  Initiator uses generated keys as they are (sending key
+for sending and receiving key for receiving).
+
+The HMAC keys are used to create MAC values to packets in the
+communication channel.  As many bytes as needed are taken from the start
+of the hash output to generate the MAC keys.
+
+These procedures are performed by all parties of the key exchange
+protocol.  This MUST be done before the protocol has been ended by
+sending the SILC_PACKET_SUCCESS packet, to assure that parties can
+successfully process the key material.
+
+This same key processing procedure MAY be used in the SILC in some
+other circumstances as well.  Any changes to this procedure is defined
+separately when this procedure is needed.  See the [SILC1] and the
+[SILC2] for these circumstances.
+
+
+.ti 0
+2.4 SILC Key Exchange Groups
+
+The Following groups may be used in the SILC Key Exchange protocol.
+The first group diffie-hellman-group1 is REQUIRED, other groups MAY be
+negotiated to be used in the connection with Key Exchange Start Payload
+and SILC_PACKET_KEY_EXCHANGE packet.  However, the first group MUST be
+proposed in the Key Exchange Start Payload regardless of any other
+requested group (however, it does not have to be the first in the list).
+
+
+.ti 0
+2.4.1 diffie-hellman-group1
+
+The length of this group is 1024 bits.  This is REQUIRED group.
+The prime is 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
+
+Its hexadecimal value is
+
+.in 6
+FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381
+FFFFFFFF FFFFFFFF
+.in 3
+
+
+The generator used with this prime is g = 2.  The group order q is
+(p - 1) / 2.
+
+This group was taken from RFC 2412.
+
+
+.ti 0
+2.4.2 diffie-hellman-group2
+
+The length of this group is 1536 bits.  This is OPTIONAL group.
+The prime is 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }.
+
+Its hexadecimal value is
+
+.in 6
+FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
+C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
+83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
+670C354E 4ABC9804 F1746C08 CA237327 FFFFFFFF FFFFFFFF
+.in 3
+
+The generator used with this prime is g = 2.  The group order q is
+(p - 1) / 2.
+
+This group was taken from RFC 3526.
+
+
+.ti 0
+2.4.3 diffie-hellman-group3
+
+The length of this group is 2048 bits.  This is OPTIONAL group.
+This prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }.
+
+Its hexadecimal value is
+
+.in 6
+FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
+29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
+EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
+E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
+EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
+C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
+83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
+670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
+E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
+DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
+15728E5A 8AACAA68 FFFFFFFF FFFFFFFF
+.in 3
+
+The generator used with this prime is g = 2.  The group order q is
+(p - 1) / 2.
+
+This group was taken from RFC 3526.
+
+Additional larger groups are defined in RFC 3526 and may be used in SKE
+by defining name for them using the above name format.
+
+
+.ti 0
+2.5 Key Exchange Status Types
+
+This section defines all key exchange protocol status types that may
+be returned in the SILC_PACKET_SUCCESS or SILC_PACKET_FAILURE packets
+to indicate the status of the protocol.  Implementations may map the
+status types to human readable error message.  All types except the
+SILC_SKE_STATUS_OK type MUST be sent in SILC_PACKET_FAILURE packet.
+The length of status is 32 bits (4 bytes).  The following status types
+are defined:
+
+.in 6
+0   SILC_SKE_STATUS_OK
+
+    Protocol were executed successfully.
+
+
+1   SILC_SKE_STATUS_ERROR
+
+    Unknown error occurred.  No specific error type is defined.
+
+
+2   SILC_SKE_STATUS_BAD_PAYLOAD
+
+    Provided KE payload were malformed or included bad fields.
+
+
+3   SILC_SKE_STATUS_UNSUPPORTED_GROUP
+
+    None of the provided groups were supported.
+
+
+4   SILC_SKE_STATUS_UNSUPPORTED_CIPHER
+
+    None of the provided ciphers were supported.
+
+
+5   SILC_SKE_STATUS_UNSUPPORTED_PKCS
+
+    None of the provided public key algorithms were supported.
+
+
+6   SILC_SKE_STATUS_UNSUPPORTED_HASH_FUNCTION
+
+    None of the provided hash functions were supported.
+
+
+7   SILC_SKE_STATUS_UNSUPPORTED_HMAC
+
+    None of the provided HMACs were supported.
+
+
+8   SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY
+
+    Provided public key type is not supported.
+
+
+9   SILC_SKE_STATUS_INCORRECT_SIGNATURE
+
+    Provided signature was incorrect.
+
+
+10  SILC_SKE_STATUS_BAD_VERSION
+
+    Provided version string was not acceptable.
+
+
+11  SILC_SKE_STATUS_INVALID_COOKIE
+
+    The cookie in the Key Exchange Start Payload was malformed,
+    because responder modified the cookie.
+.in 3
+
+
+.ti 0
+3 SILC Connection Authentication Protocol
+
+Purpose of Connection Authentication protocol is to authenticate the
+connecting party with server.  Usually connecting party is client but
+server may connect to router server as well.  Its other purpose is to
+provide information for the server about which type of entity the
+connection is.  The type defines whether the connection is client,
+server or router connection.  Server use this information to create the
+ID for the connection.
+
+Server MUST verify the authentication data received and if it is to fail
+the authentication MUST be failed by sending SILC_PACKET_FAILURE packet.
+If authentication is successful the protocol is ended by server by sending
+SILC_PACKET_SUCCESS packet.
+
+The protocol is executed after the SILC Key Exchange protocol.  It MUST
+NOT be executed in any other time.  As it is performed after key exchange
+protocol all traffic in the connection authentication protocol is
+encrypted with the exchanged keys.
+
+The protocol MUST be started by the connecting party by sending the
+SILC_PACKET_CONNECTION_AUTH packet with Connection Auth Payload,
+described in the next section.  This payload MUST include the
+authentication data.  The authentication data is set according
+authentication method that MUST be known by both parties.  If connecting
+party does not know what is the mandatory authentication method it MAY
+request it from the server by sending SILC_PACKET_CONNECTION_AUTH_REQUEST
+packet.  This packet is not part of this protocol and is described in
+section Connection Auth Request Payload in [SILC2].  However, if
+connecting party already knows the mandatory authentication method
+sending the request is not necessary.
+
+See [SILC1] and section Connection Auth Request Payload in [SILC2] also
+for the list of different authentication methods.  Authentication method
+MAY also be NONE, in which case the server does not require
+authentication.  However, in this case the protocol still MUST be
+executed; the authentication data is empty indicating no authentication
+is required.
+
+If authentication method is passphrase the authentication data is
+plaintext passphrase.  As the payload is encrypted it is safe to have
+plaintext passphrase.  It is also provided as plaintext passphrase
+because the receiver may need to pass the entire passphrase into a
+passphrase verifier, and a message digest of the passphrase would
+prevent this.  See the section 3.2.1 Passphrase Authentication for
+more information.
+
+If authentication method is public key authentication the authentication
+data is a digital signature of the hash value of hash HASH and Key
+Exchange Start Payload, established by the SILC Key Exchange protocol.
+This signature MUST then be verified by the server.  See the section
+3.2.2 Public Key Authentication for more information.
+
+See the section 4 SILC Procedures in [SILC1] for more information about
+client creating connection to server, and server creating connection
+to router, and how to register the session in the SILC Network after
+successful Connection Authentication protocol.
+
+
+.ti 0
+3.1 Connection Auth Payload
+
+Client sends this payload to authenticate itself to the server.  Server
+connecting to another server also sends this payload.  Server receiving
+this payload MUST verify all the data in it and if something is to fail
+the authentication MUST be failed by sending SILC_PACKET_FAILURE packet.
+
+The payload may only be sent with SILC_PACKET_CONNECTION_AUTH packet.
+It MUST NOT be sent in any other packet type.  The following diagram
+represent the Connection Auth Payload.
+
+
+
+
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Payload Length         |        Connection Type        |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                     Authentication Data                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 3:  Connection Auth Payload
+
+
+.in 6
+o Payload Length (2 bytes) - Length of the entire Connection
+  Auth Payload.
+
+o Connection Type (2 bytes) - Indicates the type of the
+  connection.  See section Connection Auth Request Payload
+  in [SILC2] for the list of connection types.  This field MUST
+  include valid connection type or the packet MUST be discarded
+  and authentication MUST be failed.
+
+o Authentication Data (variable length) - The actual
+  authentication data.  Contents of this depends on the
+  authentication method known by both parties.  If no
+  authentication is required this field does not exist.
+.in 3
+
+
+.ti 0
+3.2 Connection Authentication Types
+
+SILC supports two authentication types to be used in the connection
+authentication protocol; passphrase authentication or public key
+authentication based on digital signatures.  The following sections
+defines the authentication methods.  See [SILC2] for defined numerical
+authentication method types.
+
+
+.ti 0
+3.2.1 Passphrase Authentication
+
+Passphrase authentication or pre-shared key based authentication is
+simply an authentication where the party that wants to authenticate
+itself to the other end sends the passphrase that is required by
+the other end, for example server.  The plaintext passphrase is put
+to the payload, that is then encrypted.  The plaintext passphrase
+MUST be in UTF-8 [RFC2279] encoding.  If the passphrase is in the
+sender's system in some other encoding it MUST be UTF-8 encoded
+before transmitted.  The receiver MAY change the encoding of the
+passphrase to its system's default character encoding before verifying
+the passphrase.
+
+If the passphrase matches with the one in the server's end the
+authentication is successful.  Otherwise SILC_PACKET_FAILURE MUST be
+sent to the sender and the protocol execution fails.
+
+This is REQUIRED authentication method to be supported by all SILC
+implementations.
+
+When password authentication is used it is RECOMMENDED that maximum
+amount of padding is applied to the SILC packet.  This way it is not
+possible to approximate the length of the password from the encrypted
+packet.
+
+
+
+.ti 0
+3.2.2 Public Key Authentication
+
+Public key authentication may be used if passphrase based authentication
+is not desired.  The public key authentication works by sending a
+digital signature as authentication data to the other end, say, server.
+The server MUST then verify the signature by the public key of the sender,
+which the server has received earlier in SKE protocol.
+
+The signature is computed using the private key of the sender by signing
+the HASH value provided by the SKE protocol previously, and the Key
+Exchange Start Payload from SKE protocol that was sent to the server.
+These are concatenated and hash function is used to compute a hash value
+which is then signed.
+
+  auth_hash = hash(HASH | Key Exchange Start Payload);
+  signature = sign(auth_hash);
+
+The hash() function used to compute the value is the hash function
+negotiated in the SKE protocol.  The server MUST verify the data, thus
+it must keep the HASH and the Key Exchange Start Payload saved during
+SKE and authentication protocols.  These values can be discarded after
+Connection Authentication protocol is completed.
+
+If the verified signature matches the sent signature, the authentication
+were successful and SILC_PACKET_SUCCESS is sent.  If it failed the
+protocol execution is stopped and SILC_PACKET_FAILURE is sent.
+
+This is REQUIRED authentication method to be supported by all SILC
+implementations.
+
+
+
+.ti 0
+3.3 Connection Authentication Status Types
+
+This section defines all connection authentication status types that
+may be returned in the SILC_PACKET_SUCCESS or SILC_PACKET_FAILURE packets
+to indicate the status of the protocol.  Implementations may map the
+status types to human readable error message.  All types except the
+SILC_AUTH_STATUS_OK type MUST be sent in SILC_PACKET_FAILURE packet.
+The length of status is 32 bits (4 bytes).  The following status types
+are defined:
+
+0   SILC_AUTH_OK
+
+    Protocol was executed successfully.
+
+
+1   SILC_AUTH_FAILED
+
+    Authentication failed.
+
+
+.ti 0
+4 Security Considerations
+
+Security is central to the design of this protocol, and these security
+considerations permeate the specification.  Common security considerations
+such as keeping private keys truly private and using adequate lengths for
+symmetric and asymmetric keys must be followed in order to maintain the
+security of this protocol.
+
+
+.ti 0
+5 References
+
+[SILC1]      Riikonen, P., "Secure Internet Live Conferencing (SILC),
+             Protocol Specification", Internet Draft, June 2003.
+
+[SILC2]      Riikonen, P., "SILC Packet Protocol", Internet Draft,
+             June 2003.
+
+[SILC4]      Riikonen, P., "SILC Commands", Internet Draft, June 2003.
+
+[IRC]        Oikarinen, J., and Reed D., "Internet Relay Chat Protocol",
+             RFC 1459, May 1993.
+
+[IRC-ARCH]   Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+             April 2000.
+
+[IRC-CHAN]   Kalt, C., "Internet Relay Chat: Channel Management", RFC
+             2811, April 2000.
+
+[IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+             2812, April 2000.
+
+[IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+             2813, April 2000.
+
+[SSH-TRANS]  Ylonen, T., et al, "SSH Transport Layer Protocol",
+             Internet Draft.
+
+[PGP]        Callas, J., et al, "OpenPGP Message Format", RFC 2440,
+             November 1998.
+
+[SPKI]       Ellison C., et al, "SPKI Certificate Theory", RFC 2693,
+             September 1999.
+
+[PKIX-Part1] Housley, R., et al, "Internet X.509 Public Key
+             Infrastructure, Certificate and CRL Profile", RFC 2459,
+             January 1999.
+
+[Schneier]   Schneier, B., "Applied Cryptography Second Edition",
+             John Wiley & Sons, New York, NY, 1996.
+
+[Menezes]    Menezes, A., et al, "Handbook of Applied Cryptography",
+             CRC Press 1997.
+
+[OAKLEY]     Orman, H., "The OAKLEY Key Determination Protocol",
+             RFC 2412, November 1998.
+
+[ISAKMP]     Maughan D., et al, "Internet Security Association and
+             Key Management Protocol (ISAKMP)", RFC 2408, November
+             1998.
+
+[IKE]        Harkins D., and Carrel D., "The Internet Key Exchange
+             (IKE)", RFC 2409, November 1998.
+
+[HMAC]       Krawczyk, H., "HMAC: Keyed-Hashing for Message
+             Authentication", RFC 2104, February 1997.
+
+[PKCS1]      Kalinski, B., and Staddon, J., "PKCS #1 RSA Cryptography
+             Specifications, Version 2.0", RFC 2437, October 1998.
+
+[RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
+             Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 2279, January 1998.
+
+
+.ti 0
+6 Author's Address
+
+.nf
+Pekka Riikonen
+Snellmaninkatu 34 A 15
+70100 Kuopio
+Finland
+
+EMail: priikone@iki.fi
+
+
+.ti 0
+7 Full Copyright Statement
+
+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.
index ab7998cc211f430f6a9146a9cbfe083413959759..017f49cafd7fdea8cd7944885c39bfd5ef40fd0a 100644 (file)
@@ -8,7 +8,7 @@
 .ds RF FORMFEED[Page %]
 .ds CF
 .ds LH Internet Draft
-.ds RH 11 August 2003
+.ds RH 11 February 2004
 .ds CH
 .na
 .hy 0
@@ -16,8 +16,8 @@
 .nf
 Network Working Group                                        P. Riikonen
 Internet-Draft
-draft-riikonen-silc-pp-08.txt                             11 August 2003
-Expires: 11 February 2004
+draft-riikonen-silc-pp-08.txt                           11 February 2004
+Expires: 11 August 2004
 
 .in 3
 
@@ -87,23 +87,23 @@ Table of Contents
       2.3.3 Disconnect Payload .................................. 23
       2.3.4 Success Payload ..................................... 23
       2.3.5 Failure Payload ..................................... 24
-      2.3.6 Reject Payload ...................................... 24
+      2.3.6 Reject Payload ...................................... 25
       2.3.7 Notify Payload ...................................... 25
       2.3.8 Error Payload ....................................... 34
-      2.3.9 Channel Message Payload ............................. 34
+      2.3.9 Channel Message Payload ............................. 35
       2.3.10 Channel Key Payload ................................ 35
       2.3.11 Private Message Payload ............................ 37
       2.3.12 Private Message Key Payload ........................ 37
       2.3.13 Command Payload .................................... 39
       2.3.14 Command Reply Payload .............................. 40
       2.3.15 Connection Auth Request Payload .................... 40
-      2.3.16 New ID Payload ..................................... 41
+      2.3.16 New ID Payload ..................................... 42
       2.3.17 New Client Payload ................................. 42
       2.3.18 New Server Payload ................................. 43
       2.3.19 New Channel Payload ................................ 44
       2.3.20 Key Agreement Payload .............................. 45
       2.3.21 Resume Router Payload .............................. 46
-      2.3.22 File Transfer Payload .............................. 46
+      2.3.22 File Transfer Payload .............................. 47
       2.3.23 Resume Client Payload .............................. 48
   2.4 SILC ID Types ............................................. 49
   2.5 Packet Encryption And Decryption .......................... 49
@@ -111,12 +111,12 @@ Table of Contents
       2.5.2 Channel Message Encryption And Decryption ........... 50
       2.5.3 Private Message Encryption And Decryption ........... 51
   2.6 Packet MAC Generation ..................................... 52
-  2.7 Packet Padding Generation ................................. 52
+  2.7 Packet Padding Generation ................................. 53
   2.8 Packet Compression ........................................ 53
-  2.9 Packet Sending ............................................ 53
+  2.9 Packet Sending ............................................ 54
   2.10 Packet Reception ......................................... 54
   2.11 Packet Routing ........................................... 54
-  2.12 Packet Broadcasting ...................................... 55
+  2.12 Packet Broadcasting ...................................... 56
 3 Security Considerations ....................................... 56
 4 References .................................................... 56
 5 Author's Address .............................................. 58
@@ -505,14 +505,15 @@ List of SILC Packet types are defined as follows.
 
      10   SILC_PACKET_PRIVATE_MESSAGE_KEY
 
-          This packet can be used to agree about a key to be used to
-          protect private messages between two clients.  This packet
-          is sent inside the SILC network and protected with session
-          keys.  There are other means of agreeing to use private message
-          keys as well, than sending this packet which may not be
-          desirable on all situations.  See the [SILC1] for private
-          message key generation.  This packet MAY be sent to entity
-          that is indirectly connected to the sender.
+          This packet is OPTIONAL and sender of the packet can indicate
+          that a private message key should be used in private message
+          communication.  The actual key material is not sent in this
+          packet but must be either static or pre-shared key.  The
+          receiver of the packet is considered to be the responder
+          when processing the static or pre-shared key material as
+          defined in [SILC1] and [SILC3] for private message keys.
+          This packet MAY be sent to entity that is indirectly connected
+          to the sender.
 
           Payload of the packet:  See section 2.3.12 Private Message
                                   Key Payload
@@ -542,7 +543,6 @@ List of SILC Packet types are defined as follows.
                                   Payload
 
 
-
      13   SILC_PACKET_KEY_EXCHANGE
 
           This packet is used to start SILC Key Exchange Protocol,
@@ -882,6 +882,7 @@ o Argument Payloads (variable length) - The Argument Payloads
 
 
 
+
 .ti 0
 2.3.2.4 Channel Payload
 
@@ -1012,7 +1013,7 @@ The following diagram represents the Message Payload.
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
-~                       Initial Vector *                        ~
+~                    Initialization Vector *                    ~
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
@@ -1091,11 +1092,18 @@ o Message Flags (2 bytes) - Includes the Message Flags of the
           this flag SHOULD be used.  When this flag is used the
           text sent as message MUST be UTF-8 encoded.
 
-  0x0200 - 0x0800 RESERVED
+  0x0200  SILC_MESSAGE_FLAG_ACK
+
+          This flag indicates the sender requires the recpipient
+          to acknowledge the received message.  This same flag
+          is used in the acknowledgement.  A separate document
+          should define how the acknowledgement is performed.
+
+  0x0400 - 0x1000 RESERVED
 
           Reserved for future flags.
 
-  0x1000 - 0x8000 PRIVATE RANGE
+  0x2000 - 0x8000 PRIVATE RANGE
 
           Private range for free use.
 
@@ -1119,8 +1127,8 @@ o Padding (variable length) - If this payload is used as
   Padding Length field includes a zero (0) value.  The
   padding SHOULD be random data.
 
-o Initial Vector (variable length) - This field MUST be
-  present when this payload is used as channel messages.
+o Initialization Vector (variable length) - This field MUST
+  be present when this payload is used as channel messages.
   The IV SHOULD be random data for each channel message.
 
   When encrypting private messages with session keys this
@@ -1134,7 +1142,7 @@ o Initial Vector (variable length) - This field MUST be
   in [SILC1] for more information about IVs when
   encrypting private messages.
 
-  This field includes the initial vector used in message
+  This field includes the initialization vector used in message
   encryption.  It need to be used in the packet decryption
   as well.  Contents of this field depends on the encryption
   algorithm and encryption mode.  This field is not encrypted,
@@ -1144,11 +1152,11 @@ o Initial Vector (variable length) - This field MUST be
 
 o MAC (variable length) - The MAC computed from the
   Message Flags, Message Length, Message Data, Padding Length,
-  Padding and Initial Vector fields in that order.  The MAC
-  is computed after the payload is encrypted.  This is so
-  called Encrypt-Then-MAC order; first encrypt, then compute
-  MAC from ciphertext.  The MAC protects the integrity of
-  the Message Payload.  Also, when used as channel messages
+  Padding and Initialization Vector fields in that order.
+  The MAC is computed after the payload is encrypted.  This
+  is so called Encrypt-Then-MAC order; first encrypt, then
+  compute MAC from ciphertext.  The MAC protects the integrity
+  of the Message Payload.  Also, when used as channel messages
   it is possible to have multiple private channel keys set,
   and receiver can use the MAC to verify which of the keys
   must be used in decryption.  This field is not present
@@ -1337,12 +1345,12 @@ o Argument Nums (1 byte) - Indicates the number of Argument
   arguments to be sent along the notify message.
 .in 3
 
-The following list of currently defined notify types.  The format for
+Following the list of currently defined notify types.  The format for
 notify arguments is same as in SILC commands described in [SILC4].
 Note that all IDs sent in arguments are sent inside ID Payload.  Also
-note that all passphrases that may be sent inside arguments MUST be
-UTF-8 [RFC2279] encoded.  Also note that all public keys or certificates
-sent inside arguments are actually Public Key Payloads.
+note that all strings sent as arguments MUST be UTF-8 [RFC3629] encoded,
+unless otherwise defined.  Also note that all public keys or
+certificates sent inside arguments are actually Public Key Payloads.
 
 
 .in 6
@@ -1354,7 +1362,7 @@ sent inside arguments are actually Public Key Payloads.
       Max Arguments:  1
           Arguments:  (1) <message>
 
-      The <message> is implementation specific free UTF-8 text string.
+      The <message> is implementation specific free text string.
       Receiver MAY ignore this message.
 
 
@@ -1365,7 +1373,7 @@ sent inside arguments are actually Public Key Payloads.
       is sent to local servers on the channel, but MUST NOT be sent
       to clients on the channel.  Router MUST broadcast this to its
       primary router and to local servers on the channel.  When a client
-      was directly invited to the channel this is also sent to that 
+      was directly invited to the channel this is also sent to that
       client.  In this case the packet is destined to the client.
 
       Max Arguments:  5
@@ -1385,7 +1393,7 @@ sent inside arguments are actually Public Key Payloads.
       The <invite list> format is defined in [SILC4] with
       SILC_COMMAND_INVITE command.  When this notify is destined to
       a client the <add | del> and <invite list> MUST NOT be sent.
-      When <add | del> is used  to announce information during server 
+      When <add | del> is used  to announce information during server
       connecting phase the argument type MUST be 0x03.  See section
       4.2.1 in [SILC1] for more information.
 
@@ -1485,11 +1493,11 @@ sent inside arguments are actually Public Key Payloads.
       to the clients which are joined on the channel which mode was
       changed.  This packet is destined to the channel.
 
-      Max Arguments:  7
-          Arguments:  (1) <ID Payload>      (2) <mode mask>
-                      (3) [<cipher>]        (4) <[hmac>]
-                      (5) [<passphrase>]    (6) [<founder public key>]
-                      (7) [<channel pubkey>]
+      Max Arguments:  8
+          Arguments:  (1) <ID Payload>       (2) <mode mask>
+                      (3) [<cipher>]         (4) <[hmac>]
+                      (5) [<passphrase>]     (6) [<founder public key>]
+                      (7) [<channel pubkey>] (8) [<user limit>]
 
       The <ID Payload> is the ID (usually Client ID but it can be
       Server ID as well when the router is enforcing channel mode
@@ -1504,7 +1512,8 @@ sent inside arguments are actually Public Key Payloads.
       channel was set.  All routers and servers that receive the packet
       MUST save the founder's public key so that the founder can
       reclaim the channel founder rights back for the channel on any
-      server in the network.
+      server in the network.  The <user limit> argument is present when
+      the user limit was set or changed on the channel.
 
       The <channel pubkey> is an Argument List Payload and it is used
       to add and/or remove channel public keys from the channel.  Also,
@@ -1553,7 +1562,7 @@ sent inside arguments are actually Public Key Payloads.
           Arguments:  (1) <motd>
 
       The <motd> is the Message of the Day.  This notify MAY be
-      ignored.
+      ignored and is OPTIONAL.
 
 
 10    SILC_NOTIFY_TYPE_CHANNEL_CHANGE
@@ -1611,8 +1620,8 @@ sent inside arguments are actually Public Key Payloads.
                       (3) <Kicker's Client ID>
 
       The <Client ID> is the client which was kicked from the channel.
-      The kicker may have set the <comment> to indicate the reason for
-      the kicking.  The <Kicker's Client ID> is the kicker.
+      The kicker may have set the <comment> string to indicate the
+      reason for the kicking.  The <Kicker's Client ID> is the kicker.
 
 
 13    SILC_NOTIFY_TYPE_KILLED
@@ -1634,9 +1643,9 @@ sent inside arguments are actually Public Key Payloads.
                       (3) <Killer's ID>
 
       The <Client ID> is the client which was killed from the network.
-      The killer may have set the <comment> to indicate the reason for
-      the killing.  The <Killer's ID> is the killer, which may be
-      client but also router server.
+      The killer may have set the  <comment> string to indicate the
+      reason for the killing.  The <Killer's ID> is the killer, which
+      may be client but also router server.
 
 
 14    SILC_NOTIFY_TYPE_UMODE_CHANGE
@@ -1668,7 +1677,7 @@ sent inside arguments are actually Public Key Payloads.
       from ban list.  The <ban list> indicates the information to be
       added to or removed from the ban list.  The <ban list> format
       format is defined in [SILC4] with SILC_COMMAND_BAN command.
-      When <add | del> is used  to announce information during server 
+      When <add | del> is used  to announce information during server
       connecting phase the argument type MUST be 0x03.  See section
       4.2.1 in [SILC1] for more information.
 
@@ -1731,9 +1740,6 @@ SILC_UMODE_REJECT_WATCHING set.  If the watcher client and the client
 that was watched is same the notify SHOULD NOT be sent.
 
 
-
-
-
 .ti 0
 2.3.8 Error Payload
 
@@ -1762,7 +1768,7 @@ Figure 14:  Error Payload
 
 .in 6
 o Error Message (variable length) - Human readable error
-  message as UTF-8 string.
+  message.
 .in 3
 
 
@@ -1836,10 +1842,6 @@ represents the Channel Key Payload.
 
 
 
-
-
-
-
 .in 5
 .nf
                      1                   2                   3
@@ -1908,10 +1910,10 @@ SILC Key Exchange Protocol.  However, it is also possible to agree
 to use a private key to protect just the private messages.  It is
 for example possible to perform Key Agreement between two clients.
 See section 2.3.20 Key Agreement Payload how to perform key
-agreement.  See also section 2.3.12 Private Message Key Payload
-for another way of using private keys with private messages.  See
-[SILC1] section 4.6 for detailed description for private message
-key generation procedure.
+agreement.  It is also possible to use static or pre-shared keys
+to protect private messages.  See the 2.3.12 Private Message Key
+Payload and [SILC1] section 4.6 for detailed description for private
+message key generation.
 
 If normal session key is used to protect the message, every server
 between the sender client and the receiving client MUST decrypt the
@@ -1931,42 +1933,38 @@ See section 2.3.2.6 for generic Message Payload.
 .ti 0
 2.3.12 Private Message Key Payload
 
-This payload is OPTIONAL and can be used to send private message
-key between two clients in the network.  The packet is secured with
-normal session keys.  By default private messages are encrypted
-with session keys, and with this payload it is possible to set
-private key for private message encryption between two clients.
-
-The receiver of this payload SHOULD verify for example from user
-whether user want to receive private message key.  Note that there
-are other, more secure ways of exchanging private message keys in
-the SILC network.  Instead of sending this payload it is possible to
-negotiate the private message key with SKE protocol using the Key
-Agreement payload directly peer to peer, see section 2.3.20.
+This payload is OPTIONAL and can be used to indicate that a static
+or pre-shared key should be used in the private message communication
+to protect the messages.  The actual key material has to be sent
+outside the SILC network, or it has to be a static or pre-shared key.
+The sender of this packet is considered to be the initiator and the
+receiver the responder when processing the raw key material as
+described in the section 4.6 in [SILC1] and in the section 2.3 in
+[SILC3].
+
+Note that it is also possible to use static or pre-shared keys in
+client implementations without sending this packet.  Clients may
+naturally agree to use a key without sending any kind of indication
+to each other.  The key may be for example a long-living static key
+that the clients has agreed to use at all times.  Note that it is
+also possible to agree to use private message key by performing
+a Key Agreement.  See the section 2.3.20 Key Agreement Payload.
 
 This payload may only be sent by client to another client.  Server
-MUST NOT send this payload.  After sending this payload the sender of
-private messages must set the Private Message Key flag into SILC Packet
-Header.
+MUST NOT send this payload.  After sending this payload and setting the
+key into use this payload the sender of private messages MUST set the
+Private Message Key flag into the SILC Packet Header.
 
 The payload may only be sent with SILC_PACKET_PRIVATE_MESSAGE_KEY
 packet.  It MUST NOT be sent in any other packet type.  The following
 diagram represents the Private Message Key Payload.
 
 
-
-
 .in 5
 .nf
                      1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|  Private Message Key Length   |                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
-|                                                               |
-~                      Private Message Key                      ~
-|                                                               |
-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      Cipher Name Length       |                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
 |                                                               |
@@ -1987,13 +1985,6 @@ Figure 16:  Private Message Key Payload
 
 
 .in 6
-o Private Message Key Length (2 bytes) - Indicates the length
-  of the Private Message Key field in the payload, not including
-  any other field.
-
-o Private Message Key (variable length) - The actual private
-  message key material.
-
 o Cipher Name Length (2 bytes) - Indicates the length of the
   Cipher Name field in the payload, not including any other
   field.
@@ -2103,8 +2094,6 @@ packet.  It MUST NOT be sent in any other packet type.  The following
 diagram represents the Connection Auth Request Payload.
 
 
-
-
 .in 5
 .nf
                      1                   2                   3
@@ -2206,10 +2195,6 @@ represents the New Client Payload.
 
 
 
-
-
-
-
 .in 5
 .nf
                      1                   2                   3
@@ -2370,9 +2355,9 @@ o Hostname Length (2 bytes) - Indicates the length of the
   Hostname field.
 
 o Hostname (variable length) - The hostname or IP address where
-  the SKE protocol is running.  The sender MAY fill this field
-  when sending the payload.  If the receiver sends this payload
-  as reply to the request it MUST fill this field.
+  the SKE protocol is running, as UTF-8 encoded string.  The sender
+  MAY fill this field when sending the payload.  If the receiver
+  sends this payload as reply to the request it MUST fill this field.
 
 o Port (4 bytes) - The port where the SKE protocol is bound.
   The sender MAY fill this field when sending the payload.  If
@@ -2423,6 +2408,8 @@ o Session ID (1 bytes) - Indicates the session ID for the
 .in 3
 
 
+
+
 .ti 0
 2.3.22 File Transfer Payload
 
@@ -2995,8 +2982,8 @@ security of this protocol.
 [SFTP]       Ylonen T., and Lehtinen S., "Secure Shell File Transfer
              Protocol", Internet Draft, March 2001.
 
-[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
-             10646", RFC 2279, January 1998.
+[RFC3629]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 3629, November 2003.
 
 
 .ti 0
diff --git a/doc/draft-riikonen-silc-pp-09.nroff b/doc/draft-riikonen-silc-pp-09.nroff
new file mode 100644 (file)
index 0000000..1273025
--- /dev/null
@@ -0,0 +1,3030 @@
+.pl 10.0i
+.po 0
+.ll 7.2i
+.lt 7.2i
+.nr LL 7.2i
+.nr LT 7.2i
+.ds LF Riikonen
+.ds RF FORMFEED[Page %]
+.ds CF
+.ds LH Internet Draft
+.ds RH XXX
+.ds CH
+.na
+.hy 0
+.in 0
+.nf
+Network Working Group                                        P. Riikonen
+Internet-Draft
+draft-riikonen-silc-pp-08.txt                            XXX
+Expires: XXX
+
+.in 3
+
+.ce 2
+SILC Packet Protocol
+<draft-riikonen-silc-pp-09.txt>
+
+.ti 0
+Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with
+all provisions of Section 10 of RFC 2026.  Internet-Drafts are
+working documents of the Internet Engineering Task Force (IETF), its
+areas, and its working groups.  Note that other groups may also
+distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time.  It is inappropriate to use Internet-Drafts as reference
+material or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html
+
+The distribution of this memo is unlimited.
+
+
+.ti 0
+Abstract
+
+This memo describes a Packet Protocol used in the Secure Internet Live
+Conferencing (SILC) protocol, specified in the Secure Internet Live
+Conferencing, Protocol Specification [SILC1].  This protocol describes
+the packet types and packet payloads which defines the contents of the
+packets.  The protocol provides secure binary packet protocol that
+assures that the contents of the packets are secured and authenticated.
+
+
+
+
+
+
+
+
+
+.ti 0
+Table of Contents
+
+.nf
+1 Introduction ..................................................  3
+  1.1 Requirements Terminology ..................................  4
+2 SILC Packet Protocol ..........................................  4
+  2.1 SILC Packet ...............................................  4
+  2.2 SILC Packet Header ........................................  5
+  2.3 SILC Packet Types .........................................  7
+      2.3.1 SILC Packet Payloads ................................ 15
+      2.3.2 Generic payloads .................................... 15
+            2.3.2.1 ID Payload .................................. 15
+            2.3.2.2 Argument Payload ............................ 16
+            2.3.2.3 Argument List Payload ....................... 17
+            2.3.2.4 Channel Payload ............................. 18
+            2.3.2.5 Public Key Payload .......................... 19
+            2.3.2.6 Message Payload ............................. 19
+      2.3.3 Disconnect Payload .................................. 23
+      2.3.4 Success Payload ..................................... 23
+      2.3.5 Failure Payload ..................................... 24
+      2.3.6 Reject Payload ...................................... 25
+      2.3.7 Notify Payload ...................................... 25
+      2.3.8 Error Payload ....................................... 34
+      2.3.9 Channel Message Payload ............................. 35
+      2.3.10 Channel Key Payload ................................ 35
+      2.3.11 Private Message Payload ............................ 37
+      2.3.12 Private Message Key Payload ........................ 37
+      2.3.13 Command Payload .................................... 39
+      2.3.14 Command Reply Payload .............................. 40
+      2.3.15 Connection Auth Request Payload .................... 40
+      2.3.16 New ID Payload ..................................... 42
+      2.3.17 New Client Payload ................................. 42
+      2.3.18 New Server Payload ................................. 43
+      2.3.19 New Channel Payload ................................ 44
+      2.3.20 Key Agreement Payload .............................. 45
+      2.3.21 Resume Router Payload .............................. 46
+      2.3.22 File Transfer Payload .............................. 47
+      2.3.23 Resume Client Payload .............................. 48
+  2.4 SILC ID Types ............................................. 49
+  2.5 Packet Encryption And Decryption .......................... 49
+      2.5.1 Normal Packet Encryption And Decryption ............. 50
+      2.5.2 Channel Message Encryption And Decryption ........... 50
+      2.5.3 Private Message Encryption And Decryption ........... 51
+  2.6 Packet MAC Generation ..................................... 52
+  2.7 Packet Padding Generation ................................. 53
+  2.8 Packet Compression ........................................ 53
+  2.9 Packet Sending ............................................ 54
+  2.10 Packet Reception ......................................... 54
+  2.11 Packet Routing ........................................... 54
+  2.12 Packet Broadcasting ...................................... 56
+3 Security Considerations ....................................... 56
+4 References .................................................... 56
+5 Author's Address .............................................. 58
+6 Full Copyright Statement ...................................... 58
+
+.ti 0
+List of Figures
+
+.nf
+Figure 1:   Typical SILC Packet
+Figure 2:   SILC Packet Header
+Figure 3:   ID Payload
+Figure 4:   Argument Payload
+Figure 5:   Argument List Payload
+Figure 6:   Channel Payload
+Figure 7:   Public Key Payload
+Figure 8:   Message Payload
+Figure 9:   Disconnect Payload
+Figure 10:  Success Payload
+Figure 11:  Failure Payload
+Figure 12:  Reject Payload
+Figure 13:  Notify Payload
+Figure 14:  Error Payload
+Figure 15:  Channel Key Payload
+Figure 16:  Private Message Key Payload
+Figure 17:  Command Payload
+Figure 18:  Connection Auth Request Payload
+Figure 19:  New Client Payload
+Figure 20:  New Server Payload
+Figure 21:  Key Agreement Payload
+Figure 22:  Resume Router Payload
+Figure 23:  File Transfer Payload
+Figure 24:  Resume Client Payload
+
+
+.ti 0
+1. Introduction
+
+This document describes a Packet Protocol used in the Secure Internet
+Live Conferencing (SILC) protocol specified in the Secure Internet Live
+Conferencing, Protocol Specification [SILC1].  This protocol describes
+the packet types and packet payloads which defines the contents of the
+packets.  The protocol provides secure binary packet protocol that
+assures that the contents of the packets are secured and authenticated.
+The packet protocol is designed to be compact to avoid unnecessary
+overhead as much as possible.  This makes the SILC suitable also in
+environment of low bandwidth requirements such as mobile networks.  All
+packet payloads can also be compressed to further reduce the size of
+the packets.
+
+All packets in SILC network are always encrypted and their integrity
+is assured by computed MACs.  The protocol defines several packet types
+and packet payloads.  Each packet type usually has a specific packet
+payload that actually defines the contents of the packet.  Each packet
+also includes a default SILC Packet Header that provides sufficient
+information about the origin and the destination of the packet.
+
+
+.ti 0
+1.1 Requirements Terminology
+
+The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED,
+MAY, and OPTIONAL, when they appear in this document, are to be
+interpreted as described in [RFC2119].
+
+
+.ti 0
+2 SILC Packet Protocol
+
+.ti 0
+2.1 SILC Packet
+
+SILC packets deliver messages from sender to receiver securely by
+encrypting important fields of the packet.  The packet consists of
+default SILC Packet Header, Padding, Packet Payload data, and, packet
+MAC.
+
+The following diagram illustrates typical SILC packet.
+
+.in 5
+.nf
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+|   n bytes   | 1 - n bytes |      n bytes       |  n bytes
+| SILC Header |   Padding   |    Data Payload    |    MAC
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+.in 3
+
+.ce
+Figure 1:  Typical SILC Packet
+
+
+SILC Header is always the first part of the packet and its purpose
+is to provide information about the packet.  It provides for example
+the packet type, origin of the packet and the destination of the packet.
+The header is variable in length.  See the following section for
+description of SILC Packet header.  Packets without SILC header or
+with malformed SILC header MUST be dropped.
+
+Padding follows the packet header.  The purpose of the padding is to
+make the packet multiple by eight (8) or by the block size of the
+cipher used in the encryption, which ever is larger.  The maximum
+length of padding is currently 128 bytes.  The padding is always
+encrypted.  The padding is applied always, even if the packet is
+not encrypted.  See the section 2.7 Padding Generation for more
+detailed information.
+
+Data payload area follows padding and it is the actual data of the
+packet.  The packet data is the packet payloads defined in this
+protocol.  The data payload area is always encrypted.
+
+The last part of SILC packet is the packet MAC that assures the
+integrity of the packet.  See the section 2.6 Packet MAC Generation
+for more information.  If compression is used the compression is
+always applied before encryption.
+
+All fields in all packet payloads are always in MSB (most significant
+byte first) order.
+
+
+.ti 0
+2.2 SILC Packet Header
+
+The SILC packet header is applied to all SILC packets and it is
+variable in length.  The purpose of SILC Packet header is to provide
+detailed information about the packet.  The receiver of the packet
+uses the packet header to parse the packet and gain other relevant
+parameters of the packet.
+
+The following diagram represents the SILC packet header.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|         Payload Length        |     Flags     |  Packet Type  |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|   Pad Length  |    RESERVED   | Source ID Len |  Dest ID Len  |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|  Src ID Type  |                                               |
++-+-+-+-+-+-+-+-+                                               +
+|                                                               |
+~                           Source ID                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|  Dst ID Type  |                                               |
++-+-+-+-+-+-+-+-+                                               +
+|                                                               |
+~                         Destination ID                        ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 2:  SILC Packet Header
+
+.in 6
+o Payload Length (2 bytes) - Indicates the length of the
+  packet not including the padding of the packet.
+
+o Flags (1 byte) - Indicates flags to be used in packet
+  processing.  Several flags may be set by ORing the flags
+  together.
+
+  The following flags are reserved for this field:
+
+
+     No flags                  0x00
+
+       In this case the field is ignored.
+
+
+     Private Message Key       0x01
+
+       Indicates that the packet data MUST include private
+       message that is encrypted using private key set by
+       client.  Servers does not know this key and cannot
+       handle the packet, but passes it along.  See section
+       2.5.3 Private Message Encryption And Decryption for
+       more information.
+
+
+     List                      0x02
+
+       Indicates that the packet consists of list of
+       packet payloads indicated by the Packet Type field.
+       The payloads are added one after the other.  Note that
+       there are packet types that must not be used as
+       list.  Parsing of list packet is done by calculating
+       the length of each payload and parsing them one by
+       one.
+
+
+     Broadcast                 0x04
+
+       Marks the packet to be broadcasted.  Client and normal
+       server cannot send broadcast packets.  Only router server
+       may send broadcast packet.  The router receiving of packet
+       with this flag set MUST send (broadcast) the packet to
+       its primary route.  If router has several router connections
+       the packet may be sent only to the primary route.  See
+       section 2.12 Packet Broadcasting for description of
+       packet broadcasting.
+
+
+     Compressed                0x08
+
+       Marks that the payload of the packet is compressed.
+       The sender of the packet marks this flag when it
+       compresses the payload, and any server or router
+       en route to the recipient MUST NOT unset this flag.
+       See section 2.8 Packet Compression for description of
+       packet compressing.
+
+.in 3
+
+o Packet Type (1 byte) - Indicates the type of the packet.
+  Receiver uses this field to parse the packet.  See section
+  2.3 SILC Packets for list of defined packet types.
+
+o Pad Length (1 byte) - Indicates the length of the padding
+  applied after the SILC Packet header.  Maximum length for
+  padding is 128 bytes.
+
+o RESERVED (1 byte) - Reserved field and must include a
+  zero (0) value.
+
+o Source ID Length (1 byte) - Indicates the length of the
+  Source ID field in the header, not including this or any
+  other fields.
+
+o Destination ID Length (1 byte) - Indicates the length of the
+  Destination ID field in the header, not including this or
+  any other fields.
+
+o Src ID Type (1 byte) - Indicates the type of ID in the
+  Source ID field.  See section 2.4 SILC ID Types for
+  defined ID types.
+
+o Source ID (variable length) - The actual source ID that
+  indicates which is the original sender of the packet.
+
+o Dst ID Type (1 byte) - Indicates the type of ID in the
+  Destination ID field.  See section 2.4 SILC ID Types for
+  defined ID types.
+
+o Destination ID (variable length) - The actual destination
+  ID that indicates which is the end receiver of the packet.
+
+
+
+.ti 0
+2.3 SILC Packet Types
+
+SILC packet types defines the contents of the packet and it is used by
+the receiver to parse the packet.  The packet type is 8 bits in length.
+The range for the packet types are from 0 - 255, where 0 is never sent and
+255 is currently reserved for future extensions and MUST NOT be defined to
+any other purpose.  Every SILC specification compliant implementation
+SHOULD support all the following packet types.
+
+The below list of the SILC Packet types includes reference to the packet
+payload as well.  Packet payloads are the actual packet data area.  Each
+packet type defines packet payload which usually may only be sent with
+the specific packet type.
+
+Most of the packets are packets that must be destined directly to entity
+that is connected to the sender.  It is not allowed, for example, for a
+router to send SILC_PACKET_DISCONNECT packet to client that is not
+directly connected to the router.  However, there are some special packet
+types that may be destined to some entity that the sender does not have
+direct connection with.  These packets are for example private message
+packets, channel message packets, command packets and some other packets
+that may be broadcasted in the SILC network.  The following packet
+desription list will define it separately if a packet is allowed to be
+sent to indirectly connected entity.  Other packets MUST NOT be sent or
+accepted, if sent, to indirectly connected entities.
+
+Some packets MAY be sent as lists by adding the List flag to the Packet
+Header and constructing multiple packet payloads one after the other.
+When this is allowed it is separately defined in the following list.
+Other packets MUST NOT be sent as list and the List flag MUST NOT be set.
+
+
+List of SILC Packet types are defined as follows.
+
+.in 1
+     0    SILC_PACKET_NONE
+
+          This type is reserved and it is never sent.
+
+
+     1    SILC_PACKET_DISCONNECT
+
+          This packet is sent to disconnect the remote end.  Reason of
+          the disconnection is sent inside the packet payload.
+
+          Payload of the packet:  See section 2.3.3 Disconnect Payload
+
+
+     2    SILC_PACKET_SUCCESS
+
+          This packet is sent upon successful execution of a protocol.
+          The status of the success is sent in the packet payload.
+
+          Payload of the packet:  See section 2.3.4 Success Payload
+
+
+     3    SILC_PACKET_FAILURE
+
+          This packet is sent upon failure of a protocol.  The status
+          of the failure is sent in the packet payload.
+
+          Payload of the packet:  See section 2.3.5 Failure Payload
+
+
+     4    SILC_PACKET_REJECT
+
+          This packet MAY be sent upon rejection of a protocol.  The
+          status of the rejection is sent in the packet payload.
+
+          Payload of the packet:  See section 2.3.6 Reject Payload
+
+
+     5    SILC_PACKET_NOTIFY
+
+          This packet is used to send notify message.  The packet is
+          usually sent between server and client, but also between
+          server and router.  Client MUST NOT send this packet.  Server
+          MAY destine this packet to channel as well when the packet is
+          distributed to all clients on the channel.  This packet MAY
+          be sent as list.
+
+          Payload of the packet:  See section 2.3.7 Notify Payload.
+
+
+     6    SILC_PACKET_ERROR
+
+          This packet is sent when an error occurs.  Server MAY
+          send this packet.  Client MUST NOT send this packet.  The
+          client MAY entirely ignore the packet, however, server is
+          most likely to take action anyway.  This packet MAY be sent
+          to entity that is indirectly connected to the sender.
+
+          Payload of the packet:  See section 2.3.8 Error Payload.
+
+
+     7    SILC_PACKET_CHANNEL_MESSAGE
+
+          This packet is used to send messages to channels.  The packet
+          includes Channel ID of the channel and the actual message to
+          the channel.  Messages sent to the channel are always protected
+          by channel specific keys.  This packet MAY be sent to entity
+          that is indirectly connected to the sender.
+
+          Payload of the packet:  See section 2.3.9 Channel Message
+                                  Payload
+
+
+     8    SILC_PACKET_CHANNEL_KEY
+
+          This packet is used to distribute new key for particular
+          channel when server generates it.  Each channel has their own
+          independent keys that is used to protect the traffic on the
+          channel.  It is also possible to use channel private keys that
+          are not server generated.  In this case this packet is not used.
+          Client MUST NOT send this packet.  This packet MAY be sent to
+          entity that is indirectly connected to the sender.
+
+          Payload of the packet:  See section 2.3.10 Channel Key Payload
+
+
+     9    SILC_PACKET_PRIVATE_MESSAGE
+
+          This packet is used to send private messages from client
+          to another client.  By default, private messages are protected
+          by session keys established by normal key exchange protocol.
+          However, it is possible to use specific key to protect private
+          messages.  See [SILC1] for private message key generation.
+          This packet MAY be sent to entity that is indirectly connected
+          to the sender.
+
+          Payload of the packet:  See section 2.3.11 Private Message
+                                  Payload
+
+
+     10   SILC_PACKET_PRIVATE_MESSAGE_KEY
+
+          This packet is OPTIONAL and sender of the packet can indicate
+          that a private message key should be used in private message
+          communication.  The actual key material is not sent in this
+          packet but must be either static or pre-shared key.  The
+          receiver of the packet is considered to be the responder
+          when processing the static or pre-shared key material as
+          defined in [SILC1] and [SILC3] for private message keys.
+          This packet MAY be sent to entity that is indirectly connected
+          to the sender.
+
+          Payload of the packet:  See section 2.3.12 Private Message
+                                  Key Payload
+
+
+     11   SILC_PACKET_COMMAND
+
+          This packet is used to send commands from client to server.
+          Server MAY send this packet to other servers as well.  All
+          commands are listed in their own section SILC Command Types
+          in [SILC4].  The contents of this packet is command specific.
+          This packet MAY be sent to entity that is indirectly connected
+          to the sender.
+
+          Payload of the packet:  See section 2.3.13 Command Payload
+
+
+     12   SILC_PACKET_COMMAND_REPLY
+
+          This packet is sent as reply to the SILC_PACKET_COMMAND packet.
+          The contents of this packet is command specific.  This packet
+          MAY be sent to entity that is indirectly connected to the
+          sender.  This packet MAY be sent as list.
+
+          Payload of the packet:  See section 2.3.14 Command Reply
+                                  Payload and section 2.3.13 Command
+                                  Payload
+
+
+     13   SILC_PACKET_KEY_EXCHANGE
+
+          This packet is used to start SILC Key Exchange Protocol,
+          described in detail in [SILC3].
+
+          Payload of the packet:  Payload of this packet is described
+                                  in the section SILC Key Exchange
+                                  Protocol and its sub sections in
+                                  [SILC3].
+
+
+     14   SILC_PACKET_KEY_EXCHANGE_1
+
+          This packet is used as part of the SILC Key Exchange Protocol.
+
+          Payload of the packet:  Payload of this packet is described
+                                  in the section SILC Key Exchange
+                                  Protocol and its sub sections in
+                                  [SILC3].
+
+
+     15   SILC_PACKET_KEY_EXCHANGE_2
+
+          This packet is used as part of the SILC Key Exchange Protocol.
+
+          Payload of the packet:  Payload of this packet is described
+                                  in the section SILC Key Exchange
+                                  Protocol and its sub sections in
+                                  [SILC3].
+
+
+     16   SILC_PACKET_CONNECTION_AUTH_REQUEST
+
+          This packet is used to request an authentication method to
+          be used in the SILC Connection Authentication Protocol.  If
+          initiator of the protocol does not know the mandatory
+          authentication method this packet MAY be used to determine it.
+          The party receiving this payload SHOULD respond with the same
+          packet including the mandatory authentication method.
+
+          Payload of the packet:  See section 2.3.15 Connection Auth
+                                  Request Payload
+
+
+     17   SILC_PACKET_CONNECTION_AUTH
+
+          This packet is used to start and perform the SILC Connection
+          Authentication Protocol.  This protocol is used to authenticate
+          the connecting party.  The protocol is described in detail in
+          [SILC3].
+
+          Payload of the packet:  Payload of this packet is described
+                                  in the section SILC Authentication
+                                  Protocol and it sub sections in [SILC].
+
+
+     18   SILC_PACKET_NEW_ID
+
+          This packet is used to distribute new IDs from server to
+          router and from router to all other routers in SILC network.
+          This is used when for example new client is registered to
+          SILC network.  The newly created IDs of these operations are
+          distributed by this packet.  Only server may send this packet,
+          however, client MUST be able to receive this packet.  This
+          packet MAY be sent to entity that is indirectly connected
+          to the sender.  This packet MAY be sent as list.
+
+          Payload of the packet:  See section 2.3.16 New ID Payload
+
+
+     19   SILC_PACKET_NEW_CLIENT
+
+          This packet is used by client to register itself to the
+          SILC network.  This is sent after key exchange and
+          authentication protocols has been completed.  Client sends
+          various information about itself in this packet to the server.
+
+          Payload of the packet:  See section 2.3.17 New Client Payload
+
+
+     20   SILC_PACKET_NEW_SERVER
+
+          This packet is used by server to register itself to the
+          SILC network.  This is sent after key exchange and
+          authentication protocols has been completed.  Server sends
+          this to the router it connected to, or, if router was
+          connecting, to the connected router.  Server sends its
+          Server ID and other information in this packet.  The client
+          MUST NOT send or receive this packet.
+
+          Payload of the packet:  See section 2.3.18 New Server Payload
+
+
+     21   SILC_PACKET_NEW_CHANNEL
+
+          This packet is used to notify routers about newly created
+          channel.  Channels are always created by the router and it MUST
+          notify other routers about the created channel.  Router sends
+          this packet to its primary route.  Client MUST NOT send this
+          packet.  This packet MAY be sent to entity that is indirectly
+          connected to the sender.  This packet MAY be sent as list.
+
+          Payload of the packet:  See section 2.3.19 New Channel Payload
+
+
+     22   SILC_PACKET_REKEY
+
+          This packet is used to indicate that re-key must be performed
+          for session keys.  See section Session Key Regeneration in
+          [SILC1] for more information.  This packet does not have
+          a payload.
+
+
+     23   SILC_PACKET_REKEY_DONE
+
+          This packet is used to indicate that re-key is performed and
+          new keys must be used hereafter.  This packet does not have a
+          payload.
+
+
+     24   SILC_PACKET_HEARTBEAT
+
+          This packet is used by clients, servers and routers to keep the
+          connection alive.  It is RECOMMENDED that all servers implement
+          keepalive actions and perform it to both direction in a link.
+          This packet does not have a payload.
+
+
+     25   SILC_PACKET_KEY_AGREEMENT
+
+          This packet is used by clients to request key negotiation
+          between another client in the SILC network.  If the negotiation
+          is started it is performed using the SKE protocol.  The result of
+          the negotiation, the secret key material, can be used for
+          example as private message key.  The server and router MUST NOT
+          send this packet.
+
+          Payload of the packet:  See section 2.3.20 Key Agreement Payload
+
+
+     26   SILC_PACKET_RESUME_ROUTER
+
+          This packet is used during backup router protocol when the
+          original primary router of the cell comes back online and wishes
+          to resume the position as being the primary router of the cell.
+
+          Payload of the packet:  See section 2.3.21 Resume Router Payload
+
+
+     27   SILC_PACKET_FTP
+
+          This packet is used to perform an file transfer protocol in the
+          SILC session with some entity in the network.  The packet is
+          multi purpose.  The packet is used to tell other entity in the
+          network that the sender wishes to perform an file transfer
+          protocol.  The packet is also used to actually tunnel the
+          file transfer protocol stream.  The file transfer protocol
+          stream is always protected with the SILC binary packet protocol.
+
+          Payload of the packet:  See section 2.3.22 File Transfer Payload
+
+
+     28   SILC_PACKET_RESUME_CLIENT
+
+          This packet is used to resume a client back to the network
+          after it has been detached.  A client is able to detach from
+          the network but the client is still valid client in the network.
+          The client may then later resume its session back by sending
+          this packet to a server.  Routers also use this packet to notify
+          other routers in the network that the detached client has resumed.
+
+          Payload of the packet:  See section 2.3.23 Resume Client Payload
+
+
+     29 - 199
+
+          Currently undefined commands.
+
+
+     200 - 254
+
+          These packet types are reserved for private use and they will
+          not be defined by this document.
+
+
+     255  SILC_PACKET_MAX
+
+          This type is reserved for future extensions and currently it
+          MUST NOT be sent.
+.in 3
+
+
+.ti 0
+2.3.1 SILC Packet Payloads
+
+All payloads resides in the main data area of the SILC packet.  However
+all payloads MUST be at the start of the data area after the SILC
+packet header and padding.  All fields in the packet payload are always
+encrypted, as they reside in the data area of the packet which is
+always encrypted.  Most of the payloads may only be sent with specific
+packet type which is defined in the description of the payload.
+
+There are some other payloads in SILC as well.  However, they are not
+common in the sense that they could be sent at any time.  These payloads
+are not described in this section.  These are payloads such as SILC
+Key Exchange payloads and so on.  These are described in [SILC1],
+[SILC3] and [SILC4].
+
+
+.ti 0
+2.3.2 Generic payloads
+
+This section describes generic payloads that are not associated to any
+specific packet type.  They can be used for example inside some other
+packet payload.
+
+
+.ti 0
+2.3.2.1 ID Payload
+
+This payload can be used to send an ID.  ID's are variable in length
+thus this payload provides a way to send variable length ID.
+
+The following diagram represents the ID Payload.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|             ID Type           |           ID Length           |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                           ID Data                             ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 3:  ID Payload
+
+
+.in 6
+o ID Type (2 bytes) - Indicates the type of the ID.  See
+  section 2.4 SILC ID Types for list of defined ID types.
+
+o ID Length (2 bytes) - Length of the ID Data area not
+  including the length of any other fields in the payload.
+
+o ID Data (variable length) - The actual ID data.  The encoding
+  of the ID data is defined in section 2.4 SILC ID Types.
+.in 3
+
+
+.ti 0
+2.3.2.2 Argument Payload
+
+Argument Payload is used to set arguments for any packet payload that
+need and support arguments, such as commands.  Number of arguments
+associated with a packet MUST be indicated by the packet payload which
+need the arguments.  Argument Payloads MUST always reside right after
+the packet payload needing the arguments.  Incorrect amount of argument
+payloads MUST cause rejection of the packet.
+
+The following diagram represents the Argument Payload.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|          Data Length          | Argument Type |               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               +
+|                                                               |
+~                        Argument Data                          ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 4:  Argument Payload
+
+
+.in 6
+o Data Length (2 bytes) - Length of the Argument Data field
+  not including the length of any other field in the payload.
+
+o Argument Type (1 byte) - Indicates the type of the argument.
+  Every argument can have a specific type that are defined
+  by the packet payload needing the argument.  For example
+  every command specify a number for each argument that may be
+  associated with the command.  By using this number the receiver
+  of the packet knows what type of argument this is.  If there is
+  no specific argument type this field is set to zero (0) value.
+
+o Argument Data (variable length) - Argument data.
+.in 3
+
+
+.ti 0
+2.3.2.3 Argument List Payload
+
+Argument List Payload is a list of Argument Payloads appended one
+after the other.  The number of arguments is indicated in the
+payload.
+
+The following diagram represents the Argument List Payload.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|         Argument Nums         |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                        Argument Payloads                      ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 5:  Argument List Payload
+
+
+.in 6
+o Argument Nums (2 bytes) - Indicates the number of Argument
+  Payloads.  If zero (0) value is found in this field no
+  arguments are present.
+
+o Argument Payloads (variable length) - The Argument Payloads
+  appended one after the other.  The payloads can be decoded
+  since the length of the payload is indicated in each of
+  the Argument Payload.
+.in 3
+
+
+
+
+
+.ti 0
+2.3.2.4 Channel Payload
+
+Generic Channel Payload may be used to send information about a channel,
+its name, the Channel ID and a mode.
+
+The following diagram represents the Channel Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|      Channel Name Length      |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                         Channel Name                          ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Channel ID Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                          Channel ID                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                           Mode Mask                           |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 6:  New Channel Payload
+
+
+.in 6
+o Channel Name Length (2 bytes) - Length of the Channel Name
+  field.
+
+o Channel Name (variable length) - The name of the channel.
+
+o Channel ID Length (2 bytes) - Length of the Channel ID field.
+
+o Channel ID (variable length) - The encoded Channel ID.
+
+o Mode Mask (4 bytes) - A mode.  This can be the mode of the
+  channel but it can also be the mode of a client on the
+  channel.  The contents of this field is dependent of the
+  usage of this payload.  The usage is defined separately
+  when this payload is used.  This is a 32 bit MSB first value.
+.in 3
+
+
+
+
+
+
+.ti 0
+2.3.2.5 Public Key Payload
+
+Generic Public Key Payload may be used to send different type of
+public keys and certificates.
+
+The following diagram represents the Public Key Payload.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Public Key Length       |        Public Key Type        |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                  Public Key (or certificate)                  ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 7:  Public Key Payload
+
+
+.in 6
+o Public Key Length (2 bytes) - The length of the Public Key
+  (or certificate) field, not including any other field.
+
+o Public Key Type (2 bytes) - The public key (or certificate)
+  type.  This field indicates the type of the public key in
+  the packet.  See the [SILC3] for defined public key types.
+
+o Public Key (or certificate) (variable length) - The
+  encoded public key or certificate data.
+.in 3
+
+
+.ti 0
+2.3.2.6 Message Payload
+
+Generic Message Payload can be used to send messages in SILC.  It
+is used to send channel messages and private messages.
+
+The following diagram represents the Message Payload.
+
+(*) indicates that the field is not encrypted.
+
+
+
+
+
+
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Message  Flags         |         Message Length        |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                         Message Data                          ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Padding Length         |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                            Padding                            ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                    Initialization Vector *                    ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                              MAC *                            ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 8:  Message Payload
+
+
+.in 6
+o Message Flags (2 bytes) - Includes the Message Flags of the
+  message.  The flags can indicate a reason or a purpose for
+  the message.  The following Message Flags are defined:
+
+  0x0000  SILC_MESSAGE_FLAG_NONE
+
+          No specific flags set.
+
+  0x0001  SILC_MESSAGE_FLAG_AUTOREPLY
+
+          This message is an automatic reply to an earlier
+          received message.
+
+  0x0002  SILC_MESSAGE_FLAG_NOREPLY
+
+          There should not be reply messages to this
+          message.
+
+  0x0004  SILC_MESSAGE_FLAG_ACTION
+
+          The sender is performing an action and the message
+          is the indication of the action.
+
+  0x0008  SILC_MESSAGE_FLAG_NOTICE
+
+          The message is for example an informational notice
+          type message.
+
+  0x0010  SILC_MESSAGE_FLAG_REQUEST
+
+          This is a generic request flag to send request
+          messages.  A separate document should define any
+          payloads associated to this flag.
+
+  0x0020  SILC_MESSAGE_FLAG_SIGNED
+
+          This flag indicates that the message is signed
+          with sender's private key and thus can be verified
+          by the receiver using the sender's public key.  A
+          separate document should define the detailed procedure
+          of the signing process and any associated payloads
+          for this flag.
+
+  0x0040  SILC_MESSAGE_FLAG_REPLY
+
+          This is a generic reply flag to send a reply to
+          previously received request.  A separate document
+          should define any payloads associated to this flag.
+
+  0x0080  SILC_MESSAGE_FLAG_DATA
+
+          This is a generic data flag, indicating that the
+          message includes some data which can be interpreted
+          in a specific way.  Using this flag any kind of data
+          can be delivered inside message payload.  A separate
+          document should define how this flag is interpreted
+          and define any associated payloads.
+
+  0x0100  SILC_MESSAGE_FLAG_UTF8
+
+          This flag indicates that the message is UTF-8 encoded
+          textual message.  When sending text messages in SILC
+          this flag SHOULD be used.  When this flag is used the
+          text sent as message MUST be UTF-8 encoded.
+
+  0x0200  SILC_MESSAGE_FLAG_ACK
+
+          This flag indicates the sender requires the recpipient
+          to acknowledge the received message.  This same flag
+          is used in the acknowledgement.  A separate document
+          should define how the acknowledgement is performed.
+
+  0x0400 - 0x1000 RESERVED
+
+          Reserved for future flags.
+
+  0x2000 - 0x8000 PRIVATE RANGE
+
+          Private range for free use.
+
+o Message Length (2 bytes) - Indicates the length of the
+  Message Data field in the payload, not including any
+  other field.
+
+o Message Data (variable length) - The actual message data.
+
+o Padding Length (2 bytes) - Indicates the length of the
+  Padding field in the payload, not including any other
+  field.
+
+o Padding (variable length) - If this payload is used as
+  channel messages, the padding MUST be applied because
+  this payload is encrypted separately from other parts
+  of the packet.  If this payload is used as private
+  messages, the padding is present only when the payload
+  is encrypted with private message key.  If encrypted
+  with session keys this field MUST NOT be present and the
+  Padding Length field includes a zero (0) value.  The
+  padding SHOULD be random data.
+
+o Initialization Vector (variable length) - This field MUST
+  be present when this payload is used as channel messages.
+  The IV SHOULD be random data for each channel message.
+
+  When encrypting private messages with session keys this
+  field MUST NOT be present.  For private messages this
+  field is present only when encrypting with a static
+  private message key (pre-shared key).  If randomly
+  generated key material is used this field MUST NOT be
+  present.  Also, If Key Agreement (SKE) was used to
+  negotiate fresh key material for private message key
+  this field MUST NOT be present.  See the section 4.6
+  in [SILC1] for more information about IVs when
+  encrypting private messages.
+
+  This field includes the initialization vector used in message
+  encryption.  It need to be used in the packet decryption
+  as well.  Contents of this field depends on the encryption
+  algorithm and encryption mode.  This field is not encrypted,
+  is not included in padding calculation and its length
+  equals to cipher's block size.  This field is authenticated
+  by the message MAC.
+
+o MAC (variable length) - The MAC computed from the
+  Message Flags, Message Length, Message Data, Padding Length,
+  Padding and Initialization Vector fields in that order.
+  The MAC is computed after the payload is encrypted.  This
+  is so called Encrypt-Then-MAC order; first encrypt, then
+  compute MAC from ciphertext.  The MAC protects the integrity
+  of the Message Payload.  Also, when used as channel messages
+  it is possible to have multiple private channel keys set,
+  and receiver can use the MAC to verify which of the keys
+  must be used in decryption.  This field is not present
+  when encrypting private messages with session key.  This
+  field is not encrypted. This field is authenticated by
+  the SILC packet MAC.
+.in 3
+
+
+.ti 0
+2.3.3 Disconnect Payload
+
+Disconnect payload is sent upon disconnection.  Reason of the
+disconnection is sent to the disconnected party in the payload.
+
+The payload may only be sent with SILC_PACKET_DISCONNECT packet.  It
+MUST NOT be sent in any other packet type.  The following diagram
+represents the Disconnect Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|    Status     |                                               |
++-+-+-+-+-+-+-+-+                                               +
+|                                                               |
+~                      Disconnect Message                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 9:  Disconnect Payload
+
+.in 6
+o Status (1 byte) - Indicates the Status Type, defined in [SILC3]
+  for the reason of disconnection.
+
+o Disconnect Message (variable length) - Human readable UTF-8
+  encoded string indicating reason of the disconnection.  This
+  field MAY be omitted.
+.in 3
+
+
+.ti 0
+2.3.4 Success Payload
+
+Success payload is sent when some protocol execution is successfully
+completed.  The payload is simple; indication of the success is sent.
+This may be any data, including binary or human readable data, and
+it is protocol dependent.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                      Success Indication                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 10:  Success Payload
+
+
+.in 6
+o Success Indication (variable length) - Indication of
+  the success.  This may be for example some flag that
+  indicates the protocol and the success status or human
+  readable success message.  The true length of this
+  payload is available by calculating it from the SILC
+  Packet Header.
+.in 3
+
+
+.ti 0
+2.3.5 Failure Payload
+
+This is opposite of Success Payload.  Indication of failure of
+some protocol is sent in the payload.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                      Failure Indication                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 11:  Failure Payload
+
+
+.in 6
+o Failure Indication (variable length) - Indication of
+  the failure.  This may be for example some flag that
+  indicates the protocol and the failure status or human
+  readable failure message.  The true length of this
+  payload is available by calculating it from the SILC
+  Packet Header.
+.in 3
+
+
+.ti 0
+2.3.6 Reject Payload
+
+This payload is sent when some protocol is rejected to be executed.
+Other operations MAY send this as well that was rejected.  The
+indication of the rejection is sent in the payload.  The indication
+may be binary or human readable data and is protocol dependent.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                       Reject Indication                       ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 12:  Reject Payload
+
+
+.in 6
+o Reject Indication (variable length) - Indication of
+  the rejection.  This maybe for example some flag that
+  indicates the protocol and the rejection status or human
+  readable rejection message.  The true length of this
+  payload is available by calculating it from the SILC
+  Packet Header.
+.in 3
+
+
+
+.ti 0
+2.3.7 Notify Payload
+
+Notify payload is used to send notify messages.  The payload is usually
+sent from server to client and from server to router.  It is also used
+by routers to notify other routers in the network.  This payload MAY also
+be sent to a channel.  Client MUST NOT send this payload.  When this
+packet is received by client it SHOULD process it.  Servers and routers
+MUST process notify packets.
+
+The payload may only be sent with SILC_PACKET_NOTIFY packet.  It MUST
+NOT be sent in any other packet type.  The following diagram represents
+the Notify Payload.
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|          Notify Type          |        Payload Length         |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| Argument Nums |
++-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 13:  Notify Payload
+
+
+.in 6
+o Notify Type (2 bytes) - Indicates the type of the notify
+  message.
+
+o Payload Length (2 bytes) - Length of the entire Notify Payload
+  including any associated Argument Payloads.
+
+o Argument Nums (1 byte) - Indicates the number of Argument
+  Payloads associated to this payload.  Notify types may define
+  arguments to be sent along the notify message.
+.in 3
+
+Following the list of currently defined notify types.  The format for
+notify arguments is same as in SILC commands described in [SILC4].
+Note that all IDs sent in arguments are sent inside ID Payload.  Also
+note that all strings sent as arguments MUST be UTF-8 [RFC3629] encoded,
+unless otherwise defined.  Also note that all public keys or
+certificates sent inside arguments are actually Public Key Payloads.
+
+
+.in 6
+0     SILC_NOTIFY_TYPE_NONE
+
+      If no specific notify type apply for the notify message this type
+      MAY be used.
+
+      Max Arguments:  1
+          Arguments:  (1) <message>
+
+      The <message> is implementation specific free text string.
+      Receiver MAY ignore this message.
+
+
+1     SILC_NOTIFY_TYPE_INVITE
+
+      Sent when an client is invited to a channel.  This is also sent
+      when the invite list of the channel is changed.  This notify type
+      is sent to local servers on the channel, but MUST NOT be sent
+      to clients on the channel.  Router MUST broadcast this to its
+      primary router and to local servers on the channel.  When a client
+      was directly invited to the channel this is also sent to that
+      client.  In this case the packet is destined to the client.
+
+      Max Arguments:  5
+          Arguments:  (1) <Channel ID>          (2) <channel name>
+                      (3) [<sender Client ID>]  (4) [<add | del>]
+                      (5) [<invite list>]
+
+      The <Channel ID> is the channel.  The <channel name> is the name
+      of the channel and is provided because the client which receives
+      this notify packet may not have a way to resolve the name of the
+      channel from the <Channel ID>.  The <sender Client ID> is the
+      Client ID which invited the client to the channel.  The
+      <add | del> is an argument of size of 1 byte where 0x00 means
+      adding a client to invite list, and 0x01 means deleting a client
+      from invite list.  The <invite list>, if present, indicates the
+      information to be added to or removed from the invite list.
+      The <invite list> format is defined in [SILC4] with
+      SILC_COMMAND_INVITE command.  When this notify is destined to
+      a client the <add | del> and <invite list> MUST NOT be sent.
+      When <add | del> is used  to announce information during server
+      connecting phase the argument type MUST be 0x03.  See section
+      4.2.1 in [SILC1] for more information.
+
+
+2     SILC_NOTIFY_TYPE_JOIN
+
+      Sent when client has joined to a channel.  The server MUST
+      distribute this type to the local clients on the channel and then
+      send it to its primary router.  Note that, when router is joining
+      the client on behalf of normal server then router MUST send this
+      notify type locally and globally.  The router or server receiving
+      the packet distributes this type to the local clients on the
+      channel and broadcast it to the network.  This notify is sent
+      also to the client that joined the channel.
+
+      Max Arguments:  2
+          Arguments:  (1) [<Client ID>]       (2) <Channel ID>
+
+      The <Client ID> is the client that joined to the channel
+      indicated by the <Channel ID>.
+
+
+3     SILC_NOTIFY_TYPE_LEAVE
+
+      Sent when client has left a channel.  The server must distribute
+      this type to the local clients on the channel and then send it
+      to its primary router.  The router or server receiving the
+      packet distributes this type to the local clients on the channel
+      and broadcast it to the network.  This notify MUST NOT be sent to
+      the leaving client.
+
+      Max Arguments:  1
+          Arguments:  (1) <Client ID>
+
+      The <Client ID> is the client which left the channel.
+
+
+4     SILC_NOTIFY_TYPE_SIGNOFF
+
+      Sent when client signoff from SILC network.  The server MUST
+      distribute this type to the local clients on the channel and
+      then send it to its primary router.  The router or server
+      receiving the packet distributes this type to the local clients
+      on the channel and broadcast it to the network.  This notify
+      MUST NOT be sent to the quitting client.
+
+      Max Arguments:  2
+          Arguments:  (1) <Client ID>  (2) <message>
+
+      The <Client ID> is the client which left SILC network.  The
+      <message> is free text string indicating the reason of the
+      signoff.
+
+
+5     SILC_NOTIFY_TYPE_TOPIC_SET
+
+      Sent when topic is set/changed on a channel.  This type may be
+      sent only to the clients which are joined on the channel which
+      topic was just set or changed.  The packet is destined to the
+      channel.
+
+      Max Arguments:  2
+          Arguments:  (1) <ID Payload>  (2) <topic>
+
+      The <ID Payload> is the ID of the entity who set the topic.
+      It usually is Client ID but it can be Server ID and Channel ID
+      as well.
+
+
+6     SILC_NOTIFY_TYPE_NICK_CHANGE
+
+      Sent when client changes nick on a channel.  The server MUST
+      distribute this type only to the local clients on the channel
+      and then send it to its primary router.  The router or server
+      receiving the packet distributes this type to the local clients
+      on the channel and broadcast it to the network.  This packet is
+      destined directly to the sent entity.  This MUST be sent to those
+      clients that are joined on same channels as the client that
+      changed the nickname.  This notify MUST NOT be sent multiple
+      times to the same recipient.  This notify MUST be sent also to
+      the client that changed the nickname.
+
+      Max Arguments:  3
+          Arguments:  (1) <Old Client ID>  (2) <New Client ID>
+                      (3) <nickname>
+
+      The <Old Client ID> is the old ID of the client which changed
+      the nickname.  The <New Client ID> is the new ID generated by
+      the change of the nickname.  The <nickname> is the new nickname.
+      Note that it is possible to send this notify even if the
+      nickname has not changed, but client ID was changed.
+
+
+7     SILC_NOTIFY_TYPE_CMODE_CHANGE
+
+      Sent when channel mode has changed.  This type MUST be sent only
+      to the clients which are joined on the channel which mode was
+      changed.  This packet is destined to the channel.
+
+      Max Arguments:  8
+          Arguments:  (1) <ID Payload>       (2) <mode mask>
+                      (3) [<cipher>]         (4) <[hmac>]
+                      (5) [<passphrase>]     (6) [<founder public key>]
+                      (7) [<channel pubkey>] (8) [<user limit>]
+
+      The <ID Payload> is the ID (usually Client ID but it can be
+      Server ID as well when the router is enforcing channel mode
+      change) of the entity which changed the mode.  The <mode mask>
+      is the new mode mask of the channel.  The client can safely
+      ignore the <cipher> argument since the SILC_PACKET_CHANNEL_KEY
+      packet will force the new channel key change anyway.  The <hmac>
+      argument is important since the client is responsible of setting
+      the new HMAC and the hmac key into use.  The <passphrase> is
+      the passphrase of the channel, if it was now set.  The <founder
+      public key> argument is sent when the founder mode on the
+      channel was set.  All routers and servers that receive the packet
+      MUST save the founder's public key so that the founder can
+      reclaim the channel founder rights back for the channel on any
+      server in the network.  The <user limit> argument is present when
+      the user limit was set or changed on the channel.
+
+      The <channel pubkey> is an Argument List Payload and it is used
+      to add and/or remove channel public keys from the channel.  Also,
+      when announcing channel information between servers and routers
+      during connecting phase this argument includes the list of channel
+      public keys.  To add a public key to channel public key list the
+      SILC_CMODE_CHANNEL_AUTH mode is set and the argument type is 0x00,
+      and the argument is the public key.  To remove a public key from
+      the channel public key list the argument type is 0x01, and the
+      argument is the public key to be removed.  If the mode
+      SILC_CMODE_CHANNEL_AUTH is unset (and was set earlier) all public
+      keys are removed at once.  Implementation MAY add and remove
+      multiple public keys at the same time by including multiple
+      arguments to the <channel pubkey> Argument List Payload where each
+      argument is one Public Key Payload.  When <channel pubkey> is used
+      to announce information during server connecting phase the
+      argument type MUST be 0x03.  See section 4.2.1 in [SILC1] for
+      more information.
+
+
+8     SILC_NOTIFY_TYPE_CUMODE_CHANGE
+
+      Sent when user mode on channel has changed.  This type MUST be
+      sent only to the clients which are joined on the channel where
+      the target client is on.  This packet is destined to the channel.
+
+      Max Arguments:  4
+          Arguments:  (1) <ID Payload>        (2) <mode mask>
+                      (3) <Target Client ID>  (4) [<founder pubkey>]
+
+      The <ID Payload> is the ID (usually Client ID but it can be
+      Server ID as well when the router is enforcing user's mode
+      change) of the entity which changed the mode.  The <mode mask>
+      is the new mode mask of the channel.  The <Target Client ID>
+      is the client which mode was changed.  The <founder pubkey>
+      is the public key of the channel founder and may be sent only
+      when first time setting the channel founder mode using the
+      SILC_COMMAND_CUMODE command, and when sending this notify.
+
+
+9     SILC_NOTIFY_TYPE_MOTD
+
+      Sent when Message of the Day (motd) is sent to a client.
+
+      Max Arguments:  1
+          Arguments:  (1) <motd>
+
+      The <motd> is the Message of the Day.  This notify MAY be
+      ignored and is OPTIONAL.
+
+
+10    SILC_NOTIFY_TYPE_CHANNEL_CHANGE
+
+      Sent when channel's ID has changed for a reason or another.
+      This is sent by normal server to the client.  This can also be
+      sent by router to other server to force the Channel ID change.
+      The Channel ID MUST be changed to use the new one.  When sent
+      to clients, this type MUST be sent only to the clients which are
+      joined on the channel.  This packet is destined to the sent
+      entity.
+
+      Max Arguments:  2
+          Arguments:  (1) <Old Channel ID>  (2) <New Channel ID>
+
+      The <Old Channel ID> is the channel's old ID and the <New
+      Channel ID> is the new one that MUST replace the old one.
+      Server which receives this from router MUST re-announce the
+      channel to the router by sending SILC_PACKET_NEW_CHANNEL packet
+      with the new Channel ID.
+
+
+11    SILC_NOTIFY_TYPE_SERVER_SIGNOFF
+
+      Sent when server quits SILC network.  Those clients from this
+      server that are on channels must be removed from the channel.
+      This packet is destined to the sent entity.
+
+      Max Arguments:  256
+          Arguments:  (1) <Server ID>   (n) [<Client ID>]   [...]
+
+      The <Server ID> is the server's ID.  The rest of the arguments
+      are the Client IDs of the clients which are coming from this
+      server and are thus quitting the SILC network also.  If the
+      maximum number of arguments are reached another
+      SILC_NOTIFY_TYPE_SERVER_SIGNOFF notify packet MUST be sent.
+      When this notify packet is sent between routers the Client ID's
+      MAY be omitted.  Server receiving the Client ID's in the payload
+      may use them directly to remove the client.
+
+
+12    SILC_NOTIFY_TYPE_KICKED
+
+      Sent when a client has been kicked from a channel.  This MUST
+      also be sent to the client which was kicked from the channel.
+      The client which was kicked from the channel MUST be removed
+      from the channel.  The client MUST also be removed from channel's
+      invite list if it is explicitly added in the list.  This packet
+      is destined to the channel.  The router or server receiving the
+      packet distributes this type to the local clients on the channel
+      and broadcast it to the network.
+
+      Max Arguments:  3
+          Arguments:  (1) <Client ID>           (2) [<comment>]
+                      (3) <Kicker's Client ID>
+
+      The <Client ID> is the client which was kicked from the channel.
+      The kicker may have set the <comment> string to indicate the
+      reason for the kicking.  The <Kicker's Client ID> is the kicker.
+
+
+13    SILC_NOTIFY_TYPE_KILLED
+
+      Sent when a client has been killed from the network.  This MUST
+      also be sent to the client which was killed from the network.
+      This notify MUST be sent to those clients which are joined on
+      same channels as the killed client.  The client which was killed
+      MUST be removed from the network.  This packet is destined
+      directly to the sent entity.  The router or server receiving
+      the packet distributes this type to the local clients on the
+      channel and broadcast it to the network.  The client MUST also
+      be removed from joined channels invite list if it is explicitly
+      added in the lists.  This notify MUST NOT be sent multiple
+      times to same recipient.
+
+      Max Arguments:  3
+          Arguments:  (1) <Client ID>           (2) [<comment>]
+                      (3) <Killer's ID>
+
+      The <Client ID> is the client which was killed from the network.
+      The killer may have set the  <comment> string to indicate the
+      reason for the killing.  The <Killer's ID> is the killer, which
+      may be client but also router server.
+
+
+14    SILC_NOTIFY_TYPE_UMODE_CHANGE
+
+      Sent when user's mode in the SILC changes.  This type is sent
+      only between routers as broadcast packet.
+
+      Max Arguments:  2
+          Arguments:  (1) <Client ID>  (2) <mode mask>
+
+      The <Client ID> is the client which mode was changed.  The
+      <mode mask> is the new mode mask.
+
+
+15    SILC_NOTIFY_TYPE_BAN
+
+      Sent when the ban list of the channel is changed.  This notify
+      type is sent to local servers on the channel, but MUST NOT be
+      sent to clients on the channel.  Router MUST broadcast this to
+      its primary router and to local servers on the channel.
+
+      Max Arguments:  3
+          Arguments:  (1) <Channel ID>         (2) [<add | del>]
+                      (3) [<ban list>]
+
+      The <Channel ID> is the channel which ban list was changed.
+      The <add | del> is an argument of size of 1 byte where 0x00 means
+      adding a client to ban list, and 0x01 means deleting a client
+      from ban list.  The <ban list> indicates the information to be
+      added to or removed from the ban list.  The <ban list> format
+      format is defined in [SILC4] with SILC_COMMAND_BAN command.
+      When <add | del> is used  to announce information during server
+      connecting phase the argument type MUST be 0x03.  See section
+      4.2.1 in [SILC1] for more information.
+
+
+16    SILC_NOTIFY_TYPE_ERROR
+
+      Sent when an error occurs during processing some SILC procedure.
+      This is not used when error occurs during command processing, see
+      [SILC4] for more information about commands and command replies.
+      This type is sent directly to the sender of the packet whose
+      packet caused the error.  See [SILC1] for definition when this
+      type can be sent.
+
+      Max Arguments:  256
+          Arguments:  (1) <Status Type>        (n) [...]
+
+      The <Status Type> is the error type defined in [SILC4].  Note
+      that same types are also used with command replies to indicate
+      the status of a command.  Both commands and this notify type
+      share same status types.  Rest of the arguments are status type
+      dependent and are specified with those status types that can be
+      sent currently inside this notify type in [SILC4].  The <Status
+      Type> is size of 1 byte.
+
+
+17    SILC_NOTIFY_TYPE_WATCH
+
+      Sent to indicate change in a watched user.  Client can set
+      nicknames to be watched with SILC_COMMAND_WATCH command, and
+      receive notifications when they login to network, signoff from
+      the network or their user mode is changed.  This notify type
+      is used to deliver these notifications.  The notify type is
+      sent directly to the watching client.
+
+      Max Arguments:  5
+          Arguments:  (1) <Client ID>        (2) [<nickname>]
+                      (3) <user mode>        (4) [<Notify Type>]
+                      (5) [<public key>]
+
+      The <Client ID> is the user's Client ID which is being watched,
+      and the <nickname> is its nickname.  If the client just
+      changed the nickname, then <nickname> is the new nickname, but
+      the <Client ID> is the old client ID.  The <user mode> is the
+      user's current user mode.  The <Notify Type> can be same as the
+      Notify Payload's Notify Type, and is 16 bit MSB first order
+      value.  If provided it may indicate the notify that occurred
+      for the client.  If client logged in to the network the
+      <Notify Type> MUST NOT be present.  The <public key> MAY be
+      present, and it is the public key of the client being watched.
+.in 3
+
+Notify types starting from 16384 are reserved for private notify
+message types.
+
+Router server which receives SILC_NOTIFY_TYPE_SIGNOFF,
+SILC_NOTIFY_TYPE_SERVER_SIGNOFF, SILC_NOTIFY_TYPE_KILLED,
+SILC_NOTIFY_TYPE_NICK_CHANGE and SILC_NOTIFY_TYPE_UMODE_CHANGE
+MUST check whether someone in the local cell is watching the nickname
+the client has, and send the SILC_NOTIFY_TYPE_WATCH notify to the
+watcher, unless the watched client in case has the user mode
+SILC_UMODE_REJECT_WATCHING set.  If the watcher client and the client
+that was watched is same the notify SHOULD NOT be sent.
+
+
+.ti 0
+2.3.8 Error Payload
+
+Error payload is sent upon error in protocol.  Error may occur in
+various conditions when server sends this packet.  Client MUST NOT
+send this payload but MUST be able to accept it.  However, client
+MAY ignore the contents of the packet as server is going to take
+action on the error anyway.  However, it is recommended that the
+client takes error packet seriously.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                         Error Message                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 14:  Error Payload
+
+
+.in 6
+o Error Message (variable length) - Human readable error
+  message.
+.in 3
+
+
+.ti 0
+2.3.9 Channel Message Payload
+
+Channel Message Payload is used to send message to channels, a group
+of users.  These messages can only be sent if client has joined to
+some channel.  Even though this packet is very common in SILC it
+is still special packet.  Some special handling on sending and
+reception of channel message is required.
+
+Padding MUST be applied into this payload since the payload is
+encrypted separately from other parts of the packet with the
+channel specific key.  Hence the requirement of the padding.
+The packet MUST be made multiple by eight (8) or by the block
+size of the cipher, which ever is larger.
+
+The SILC header in this packet is encrypted with the session key
+of the next receiver of the packet.  Nothing else is encrypted
+with that key.  Thus, the actual packet and padding to be
+encrypted with the session key is SILC Header plus padding to it.
+
+Receiver of the the channel message packet is able to determine
+the channel the message is destined to by checking the Destination
+ID from the SILC Packet header which tells the destination channel.
+The original sender of the packet is also determined by checking
+the source ID from the header which tells the client which sent
+the message.  The Destination ID MUST be Channel ID in the SILC
+Packet header.
+
+This packet use generic Message Payload as Channel Message Payload.
+See section 2.3.2.6 for generic Message Payload.
+
+
+.ti 0
+2.3.10 Channel Key Payload
+
+All traffic in channels are protected by channel specific keys.
+Channel Key Payload is used to distribute channel keys to all
+clients on the particular channel.  Channel keys are sent when
+the channel is created, when new user joins to the channel and
+whenever a user has left a channel.  Server creates the new
+channel key and distributes it to the clients by encrypting this
+payload with the session key shared between the server and
+the client.  After that, client MUST start using the key received
+in this payload to protect the traffic on the channel.
+
+The client which is joining to the channel receives its key in the
+SILC_COMMAND_JOIN command reply message thus it is not necessary to
+send this payload to the entity which sent the SILC_COMMAND_JOIN
+command.
+
+Channel keys are cell specific thus every router in the cell have
+to create a channel key and distribute it if any client in the
+cell has joined to a channel.  Channel traffic between cell's
+are not encrypted using channel keys, they are encrypted using
+normal session keys between two routers.  Inside a cell, all
+channel traffic is encrypted with the specified channel key.
+Channel key SHOULD expire periodically, say, in one hour, in
+which case new channel key is created and distributed.
+
+Note that, this packet is not used if SILC_CMODE_PRIVKEY mode is set
+on channel.  This means that channel uses channel private keys which
+are not server generated.  For this reason server cannot send this
+packet as it does not know the key.
+
+The payload may only be sent with SILC_PACKET_CHANNEL_KEY packet.
+It MUST NOT be sent in any other packet type.  The following diagram
+represents the Channel Key Payload.
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Channel ID Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                          Channel ID                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|      Cipher Name Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                         Cipher Name                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|      Channel Key Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                         Channel Key                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 15:  Channel Key Payload
+
+
+
+.in 6
+o Channel ID Length (2 bytes) - Indicates the length of the
+  Channel ID field in the payload, not including any other
+  field.
+
+o Channel ID (variable length) - The Channel ID of the
+  channel.
+
+o Cipher Name Length (2 bytes) - Indicates the length of the
+  Cipher name field in the payload, not including any other
+  field.
+
+o Cipher Name (variable length) - Name of the cipher used
+  in the protection of channel traffic.  This name is
+  initially decided by the creator of the channel but it
+  may change during the life time of the channel as well.
+
+o Channel Key Length (2 bytes) - Indicates the length of the
+  Channel Key field in the payload, not including any other
+  field.
+
+o Channel Key (variable length) - The actual channel key
+  material.
+.in 3
+
+
+.ti 0
+2.3.11 Private Message Payload
+
+Private Message Payload is used to send private message between
+two clients.  The messages are sent only to the specified user
+and no other user inside SILC network is able to see the message.
+
+The message can be protected by the session key established by the
+SILC Key Exchange Protocol.  However, it is also possible to agree
+to use a private key to protect just the private messages.  It is
+for example possible to perform Key Agreement between two clients.
+See section 2.3.20 Key Agreement Payload how to perform key
+agreement.  It is also possible to use static or pre-shared keys
+to protect private messages.  See the 2.3.12 Private Message Key
+Payload and [SILC1] section 4.6 for detailed description for private
+message key generation.
+
+If normal session key is used to protect the message, every server
+between the sender client and the receiving client MUST decrypt the
+packet and always re-encrypt it with the session key of the next
+receiver of the packet.  See section Client To Client in [SILC1].
+
+When the private message key is used, and the Private Message Key
+flag was set in the SILC Packet header no server or router en route
+is able to decrypt or re-encrypt the packet.  In this case only the
+SILC Packet header is processed by the servers and routers en route.
+Section Client To Client in [SILC1] gives example of this scheme.
+
+This packet use generic Message Payload as Private Message Payload.
+See section 2.3.2.6 for generic Message Payload.
+
+
+.ti 0
+2.3.12 Private Message Key Payload
+
+This payload is OPTIONAL and can be used to indicate that a static
+or pre-shared key should be used in the private message communication
+to protect the messages.  The actual key material has to be sent
+outside the SILC network, or it has to be a static or pre-shared key.
+The sender of this packet is considered to be the initiator and the
+receiver the responder when processing the raw key material as
+described in the section 4.6 in [SILC1] and in the section 2.3 in
+[SILC3].
+
+Note that it is also possible to use static or pre-shared keys in
+client implementations without sending this packet.  Clients may
+naturally agree to use a key without sending any kind of indication
+to each other.  The key may be for example a long-living static key
+that the clients has agreed to use at all times.  Note that it is
+also possible to agree to use private message key by performing
+a Key Agreement.  See the section 2.3.20 Key Agreement Payload.
+
+This payload may only be sent by client to another client.  Server
+MUST NOT send this payload.  After sending this payload and setting the
+key into use this payload the sender of private messages MUST set the
+Private Message Key flag into the SILC Packet Header.
+
+The payload may only be sent with SILC_PACKET_PRIVATE_MESSAGE_KEY
+packet.  It MUST NOT be sent in any other packet type.  The following
+diagram represents the Private Message Key Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|      Cipher Name Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                          Cipher Name                          ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       HMAC Name Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           HMAC Name                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 16:  Private Message Key Payload
+
+
+
+.in 6
+o Cipher Name Length (2 bytes) - Indicates the length of the
+  Cipher Name field in the payload, not including any other
+  field.
+
+o Cipher Name (variable length) - Name of the cipher to use
+  in the private message encryption.  If this field does not
+  exist then the default cipher of the SILC protocol is used.
+  See the [SILC1] for defined ciphers.
+
+o HMAC Name Length (2 bytes) - Indicates the length of the
+  HMAC Name field in the payload, not including any other
+  field.
+
+o HMAC Name (variable length) - Name of the HMAC to use
+  in the private message MAC computation.  If this field does
+  not exist then the default HMAC of the SILC protocol is used.
+  See the [SILC1] for defined HMACs.
+.in 3
+
+
+.ti 0
+2.3.13 Command Payload
+
+Command Payload is used to send SILC commands from client to server.
+Also server MAY send commands to other servers.  The following diagram
+represents the Command Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|         Payload Length        | SILC Command  | Arguments Num |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Command Identifier      |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 17:  Command Payload
+
+
+.in 6
+o Payload Length (2 bytes) - Length of the entire command
+  payload including any command argument payloads associated
+  with this payload.
+
+o SILC Command (1 byte) - Indicates the SILC command.  This MUST
+  be set to non-zero value.  If zero (0) value is found in this
+  field the packet MUST be discarded.
+
+o Arguments Num (1 byte) - Indicates the number of arguments
+  associated with the command.  If there are no arguments this
+  field is set to zero (0).  The arguments MUST follow the
+  Command Payload.  See section 2.3.2.2 for definition of the
+  Argument Payload.
+
+o Command Identifier (2 bytes) - Identifies this command at the
+  sender's end.  The entity which replies to this command MUST
+  set the value found from this field into the Command Payload
+  used to send the reply to the sender.  This way the sender
+  can identify which command reply belongs to which originally
+  sent command.  What this field includes is implementation
+  issue but it is RECOMMENDED that wrapping counter value is
+  used in the field.
+.in 3
+
+See [SILC4] for detailed description of different SILC commands,
+their arguments and their reply messages.
+
+
+.ti 0
+2.3.14 Command Reply Payload
+
+Command Reply Payload is used to send replies to the commands.  The
+Command Reply Payload is identical to the Command Payload thus see
+the 2.3.13 section for the payload specification.
+
+The entity which sends the reply packet MUST set the Command Identifier
+field in the reply packet's Command Payload to the value it received
+in the original command packet.
+
+See SILC Commands in [SILC4] for detailed description of different
+SILC commands, their arguments and their reply messages.
+
+
+.ti 0
+2.3.15 Connection Auth Request Payload
+
+Client MAY send this payload to server to request the authentication
+method that must be used in authentication protocol.  If client knows
+this information beforehand this payload is not necessary to be sent.
+Server performing authentication with another server MAY also send
+this payload to request the authentication method.  If the connecting
+server already knows this information this payload is not necessary
+to be sent.
+
+Server receiving this request SHOULD reply with same payload sending
+the mandatory authentication method.  Algorithms that may be required
+to be used by the authentication method are the ones already
+established by the SILC Key Exchange protocol.  See section Key
+Exchange Start Payload in [SILC3] for detailed information.
+
+The payload may only be sent with SILC_PACKET_CONNECTION_AUTH_REQUEST
+packet.  It MUST NOT be sent in any other packet type.  The following
+diagram represents the Connection Auth Request Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Connection Type        |     Authentication Method     |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 18:  Connection Auth Request Payload
+
+
+.in 6
+o Connection Type (2 bytes) - Indicates the type of the
+  connection.  The following connection types are defined:
+
+
+     1    Client connection
+     2    Server connection
+     3    Router connection
+
+  If any other type is found in this field the packet MUST be
+  discarded and the authentication MUST be failed.
+
+o Authentication Method (2 bytes) - Indicates the authentication
+  method to be used in the authentication protocol.  The following
+  authentication methods are defined:
+
+     0    NONE        (mandatory)
+     1    password    (mandatory)
+     2    public key  (mandatory)
+
+  If any other type is found in this field the packet MUST be
+  discarded and the authentication MUST be failed.  If this
+  payload is sent as request to receive the mandatory
+  authentication method this field MUST be set to zero (0),
+  indicating that receiver should send the mandatory
+  authentication method.  The receiver sending this payload
+  to the requesting party, MAY also set this field to zero (0)
+  to indicate that authentication is not required.  In this
+  case authentication protocol still MUST be started but
+  server is most likely to respond with SILC_PACKET_SUCCESS
+  immediately.
+.in 3
+
+
+.ti 0
+2.3.16 New ID Payload
+
+New ID Payload is a multipurpose payload.  It is used to send newly
+created ID's from clients and servers.  When client connects to server
+and registers itself to the server by sending SILC_PACKET_NEW_CLIENT
+packet, server replies with this packet by sending the created ID for
+the client.  Server always creates the ID for the client.
+
+This payload is also used when server tells its router that new client
+has registered to the SILC network.  In this case the server sends
+the Client ID of the client to the router.  Similarly when router
+distributes information to other routers about the client in the SILC
+network this payload is used.
+
+Also, when server connects to router, router use this payload to inform
+other routers about new server in the SILC network.  However, every
+server (or router) creates their own ID's thus the ID distributed by
+this payload is not created by the distributor in this case.  Servers
+create their own ID's.  Server registers itself to the network by
+sending SILC_PACKET_NEW_SERVER to the router it connected to.  The case
+is same when router connects to another router.
+
+This payload MUST NOT be used to send information about new channels.
+New channels are always distributed by sending the dedicated
+SILC_PACKET_NEW_CHANNEL packet.  Client MUST NOT send this payload.
+Both client and server (and router) MAY receive this payload.
+
+The packet use generic ID Payload as New ID Payload.  See section
+2.3.2.1 for generic ID Payload.
+
+
+.ti 0
+2.3.17 New Client Payload
+
+When client is connected to the server, keys has been exchanged and
+connection has been authenticated, client MUST register itself to the
+server.  Client's first packet after key exchange and authentication
+protocols MUST be SILC_PACKET_NEW_CLIENT.  This payload tells server all
+the relevant information about the connected user.  Server creates a new
+client ID for the client when received this payload and sends it to the
+client in New ID Payload.
+
+This payload sends username and real name of the user on the remote host
+which is connected to the SILC server with SILC client.  The server
+creates the client ID according the information sent in this payload.
+The nickname of the user becomes the nickname sent in this payload.
+
+The payload may only be sent with SILC_PACKET_NEW_CLIENT packet.  It
+MUST NOT be sent in any other packet type.  The following diagram
+represents the New Client Payload.
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Username Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Username                            ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Real Name Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Real Name                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 19:  New Client Payload
+
+
+.in 6
+o Username Length (2 bytes) - Length of the Username field.
+
+o Username (variable length) - The username of the user on
+  the host where connecting to the SILC server.
+
+o Real Name Length (2 bytes) - Length of the Real Name field.
+
+o Real Name (variable length) - The real name of the user
+  on the host where connecting to the SILC server.
+.in 3
+
+
+.ti 0
+2.3.18 New Server Payload
+
+This payload is sent by server when it has completed successfully both
+key exchange and connection authentication protocols.  The server
+MUST register itself to the SILC Network by sending this payload.
+The first packet after these key exchange and authentication protocols
+is SILC_PACKET_NEW_SERVER packet.  The payload includes the Server ID
+of the server that it has created by itself.  It also includes a
+name of the server that is associated to the Server ID.
+
+The payload may only be sent with SILC_PACKET_NEW_SERVER packet.  It
+MUST NOT be sent in any other packet type.  The following diagram
+represents the New Server Payload.
+
+
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Server ID Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                        Server ID Data                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     Server Name Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                          Server Name                          ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 20:  New Server Payload
+
+
+.in 6
+o Server ID Length (2 bytes) - Length of the Server ID Data
+  field.
+
+o Server ID Data (variable length) - The encoded Server ID
+  data.
+
+o Server Name Length (2 bytes) - Length of the server name
+  field.
+
+o Server Name (variable length) - The server name string.
+.in 3
+
+
+.ti 0
+2.3.19 New Channel Payload
+
+Information about newly created channel is broadcasted to all routers
+in the SILC network by sending this packet payload.  Channels are
+created by router of the cell.  Server never creates channels unless
+it is a standalone server and it does not have router connection,
+in this case server acts as router.  Normal server send JOIN command
+to the router (after it has received JOIN command from client) which
+then processes the command and creates the channel.  Client MUST NOT
+send this packet.  Server MAY send this packet to a router when it is
+announcing its existing channels to the router after it has connected
+to the router.
+
+The packet use generic Channel Payload as New Channel Payload.  See
+section 2.3.2.3 for generic Channel Payload.  The Mode Mask field in the
+Channel Payload is the mode of the channel.
+
+
+.ti 0
+2.3.20 Key Agreement Payload
+
+This payload is used by clients to request key negotiation between
+another client in the SILC Network.  The key agreement protocol used
+is the SKE protocol.  The result of the protocol, the secret key
+material, can be used for example as private message key between the
+two clients.  This significantly adds security as the clients agree
+about the key without any server interaction.  The protocol is executed
+peer to peer.  The server and router MUST NOT send this payload.
+
+The sender MAY tell the receiver of this payload the hostname and the
+port where the SKE protocol is running in the sender's end.  The
+receiver MAY then initiate the SKE negotiation with the sender.  The
+sender MAY also optionally not to include the hostname and the port
+of its SKE protocol.  In this case the receiver MAY reply to the
+request by sending the same payload filled with the receiver's hostname
+and the port where the SKE protocol is running.  The sender MAY then
+initiate the SKE negotiation with the receiver.
+
+This payload may be sent with SILC_PACKET_KEY_AGREEMENT and
+SILC_PACKET_FTP packet types.  It MUST NOT be sent in any other packet
+types.  The following diagram represents the Key Agreement Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Hostname Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Hostname                            ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                             Port                              |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 21:  Key Agreement Payload
+
+
+.in 6
+o Hostname Length (2 bytes) - Indicates the length of the
+  Hostname field.
+
+o Hostname (variable length) - The hostname or IP address where
+  the SKE protocol is running, as UTF-8 encoded string.  The sender
+  MAY fill this field when sending the payload.  If the receiver
+  sends this payload as reply to the request it MUST fill this field.
+
+o Port (4 bytes) - The port where the SKE protocol is bound.
+  The sender MAY fill this field when sending the payload.  If
+  the receiver sends this payload as reply to the request it
+  MUST fill this field.  This is a 32 bit MSB first order value.
+.in 3
+
+
+After the key material has been received from the SKE protocol it is
+processed as the [SILC3] describes.  If the key material is used as
+channel private key then the Sending Encryption Key, as defined in
+[SILC3] is used as the channel private key.  Other key material must
+be discarded.  The [SILC1] in section 4.6 defines the way to use the
+key material if it is intended to be used as private message keys.
+Any other use for the key material is undefined.
+
+
+.ti 0
+2.3.21 Resume Router Payload
+
+See the [SILC1] for Resume Router protocol where this payload is
+used.  The payload may only be sent with SILC_PACKET_RESUME_ROUTER
+packet.  It MUST NOT be sent in any other packet type.  The following
+diagram represents the Resume Router Payload.
+
+
+.in 21
+.nf
+                     1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|      Type     |  Session ID   |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 22:  Resume Router Payload
+
+
+.in 6
+o Type (1 byte) - Indicates the type of the backup resume
+  protocol packet.  The type values are defined in [SILC1].
+
+o Session ID (1 bytes) - Indicates the session ID for the
+  backup resume protocol.  The sender of the packet sets this
+  value and the receiver MUST set the same value in subsequent
+  reply packet.
+.in 3
+
+
+
+
+.ti 0
+2.3.22 File Transfer Payload
+
+File Transfer Payload is used to perform file transfer protocol between
+two entities in the network.  The actual file transfer protocol is always
+encapsulated inside the SILC Packet.  The actual data stream is also sent
+peer to peer outside SILC network.
+
+When an entity, usually a client wishes to perform file transfer protocol
+with another client in the network, they perform Key Agreement protocol
+as described in the section 2.3.20 Key Agreement Payload and in [SILC3],
+inside File Transfer Payload.  After the Key Agreement protocol has been
+performed the subsequent packets in the data stream will be protected
+using the new key material.  The actual file transfer protocol is also
+initialized in this stage.  All file transfer protocol packets are always
+encapsulated in the File Transfer Payload and protected with the
+negotiated key material.
+
+The payload may only be sent with SILC_PACKET_FTP packet.  It MUST NOT
+be sent in any other packet type.  The following diagram represents the
+File Transfer Payload.
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     Type      |                                               |
++-+-+-+-+-+-+-+-+                                               +
+|                                                               |
+~                             Data                              ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 23:  File Transfer Payload
+
+
+.in 6
+o Type (1 byte) - Indicates the type of the file transfer
+  protocol.  The following file transfer protocols has been
+  defined:
+
+    1    Secure File Transfer Protocol (SFTP)  (mandatory)
+
+  If zero (0) value or any unsupported file transfer protocol
+  type is found in this field the packet MUST be discarded.
+  The currently mandatory file transfer protocol is SFTP.
+  The SFTP protocol is defined in [SFTP].
+
+o Data (variable length) - Arbitrary file transfer data.  The
+  contents and encoding of this field is dependent of the usage
+  of this payload and the type of the file transfer protocol.
+  When this payload is used to perform the Key Agreement
+  protocol, this field include the Key Agreement Payload,
+  as defined in the section 2.3.20 Key Agreement Payload.
+  When this payload is used to send the actual file transfer
+  protocol data, the encoding is defined in the corresponding
+  file transfer protocol.
+.in 3
+
+
+.ti 0
+2.3.23 Resume Client Payload
+
+This payload is used by client to resume its detached session in the
+SILC Network.  A client is able to detach itself from the network by
+sending SILC_COMMAND_DETACH command to its server.  The network
+connection to the client is lost but the client remains as valid
+client in the network.  The client is able to resume the session back
+by sending this packet and including the old Client ID, and an
+Authentication Payload [SILC1] which the server use to verify with
+the detached client's public key.  This also implies that the
+mandatory authentication method is public key authentication.
+
+Server or router that receives this from the client also sends this,
+without the Authentication Payload, to routers in the network so that
+they know the detached client has resumed.  Refer to the [SILC1] for
+detailed description how the detaching and resuming procedure is
+performed.
+
+The payload may only be sent with SILC_PACKET_RESUME CLIENT packet.  It
+MUST NOT be sent in any other packet type.  The following diagram
+represents the Resume Client Payload.
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Client ID Length        |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Client ID                           ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                     Authentication Payload                    ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 24:  Resume Client Payload
+
+
+.in 6
+o Client ID Length (1 byte) - The length of the Client ID
+  field not including any other field.
+
+o Client ID (variable length) - The detached client's Client
+  ID.  The client that sends this payload must know the Client
+  ID.
+
+o Authentication Payload (variable length) - The authentication
+  payload that the server will verify with the detached client's
+  public key.  If the server doesn't know the public key, it must
+  retrieve it for example with SILC_COMMAND_GETKEY command.
+.in 3
+
+
+
+.ti 0
+2.4 SILC ID Types
+
+ID's are used in the SILC network to associate different entities.
+The following ID's has been defined to be used in the SILC network.
+
+.in 6
+0    No ID
+
+     This is used when other ID type is available at the time.
+
+1    Server ID
+
+     Server ID to associate servers.  See the format of
+     this ID in [SILC1].
+
+2    Client ID
+
+     Client ID to associate clients.  See the format of
+     this ID in [SILC1].
+
+3    Channel ID
+
+     Channel ID to associate channels.  See the format of
+     this ID in [SILC1].
+.in 3
+
+When encoding different IDs into the ID Payload, all fields are always
+in MSB first order.  The IP address, port, and/or the random number
+are encoded in the MSB first order.
+
+
+.ti 0
+2.5 Packet Encryption And Decryption
+
+SILC packets are encrypted almost entirely.  Only the MAC at the end
+of the packet is never encrypted.  The SILC Packet header is the first
+part of a packet to be encrypted and it is always encrypted with the
+key of the next receiver of the packet.  The data payload area of the
+packet is always entirely encrypted and it is usually encrypted with
+the next receiver's key.  However, there are some special packet types
+and packet payloads that require special encryption process.  These
+special cases are described in the next sections.  First is described
+the normal packet encryption process.
+
+
+
+.ti 0
+2.5.1 Normal Packet Encryption And Decryption
+
+Normal SILC packets are encrypted with the session key of the next
+receiver of the packet.  The entire SILC Packet header and the packet
+data payload is is encrypted with the same key.  Padding of the packet
+is also encrypted always with the session key, also in special cases.
+Computed MAC of the packet MUST NOT be encrypted.
+
+Decryption process in these cases are straightforward.  The receiver
+of the packet MUST first decrypt the SILC Packet header, or some parts
+of it, usually first 16 bytes of it.  Then the receiver checks the
+packet type from the decrypted part of the header and can determine
+how the rest of the packet must be decrypted.  If the packet type is
+any of the special cases described in the following sections the packet
+decryption is special.  If the packet type is not among those special
+packet types rest of the packet can be decrypted with the same key.
+At this point the receiver is also able to determine the length of the
+packet.
+
+With out a doubt, this sort of decryption processing causes some
+overhead to packet decryption, but never the less, is required.
+
+The MAC of the packet is also verified at this point.  The MAC is
+computed from the ciphertext of the packet so it can be verified
+at this stage.  The length of the packet need to be known to be able
+to verify the MAC from the ciphertext so the first 16 bytes need to
+be decrypted to determine the packet length.  However, the MAC MUST
+be verified from the entire ciphertext.
+
+
+.ti 0
+2.5.2 Channel Message Encryption And Decryption
+
+Channel Messages (Channel Message Payload) are always encrypted with
+the channel specific key.  However, the SILC Packet header is not
+encrypted with that key.  As in normal case, the header is encrypted
+with the key of the next receiver of the packet.  Note that, in this
+case the encrypted data area is not touched at all; it MUST NOT be
+re-encrypted with the session key.
+
+Receiver of a channel message, who ever that is, is REQUIRED to decrypt
+the SILC Packet header to be able to recognize the packet to be as
+channel message.  This is same procedure as for normal SILC packets.
+As the receiver founds the packet to be channel message, rest of the
+packet processing is special.  Rest of the SILC Packet header is
+decrypted with the same session key along with the padding of the
+packet.  After that the packet is protected with the channel specific
+key and thus can be decrypted only if the receiver is the client on
+the channel.  See section 2.7 Packet Padding Generation for more
+information about padding on special packets.
+
+If the receiver of the channel message is router which is routing the
+message to another router then it MUST decrypt the Channel Message
+payload too.  Between routers (that is, between cells) channel messages
+are protected with session keys shared between the routers.  This
+causes another special packet processing for channel messages.  If
+the channel message is received from another router then the entire
+packet, including Channel Message payload, MUST be encrypted with the
+session key shared between the routers.  In this case the packet
+decryption process is as with normal SILC packets.  Hence, if the
+router is sending channel message to another router the Channel
+Message payload MUST have been decrypted and MUST be re-encrypted
+with the session key shared between the another router.  In this
+case the packet encryption is as with any normal SILC packet.
+
+It must be noted that this is only when the channel messages are sent
+from router to another router.  In all other cases the channel
+message encryption and decryption is as described before.  This
+different processing of channel messages with router to router
+connection is because channel keys are cell specific.  All cells have
+their own channel keys thus the channel message traveling from one
+cell to another MUST be protected as it would be any normal SILC
+packet.
+
+If the SILC_CMODE_PRIVKEY channel mode has been set for the channel
+then the router cannot decrypt the packet as it does not know the
+private key.  In this case the entire packet MUST be encrypted with
+the session key and sent to the router.  The router receiving the
+packet MUST check the channel mode and decrypt the packet accordingly.
+
+
+.ti 0
+2.5.3 Private Message Encryption And Decryption
+
+By default, private message in SILC are protected by session keys.
+In this case the private message encryption and decryption process is
+equivalent to normal packet encryption and decryption.
+
+However, private messages MAY be protected with private message key
+which causes the packet to be special packet.  The procedure in this
+case is very much alike to channel packets.  The actual private message
+is encrypted with the private message key and other parts of the
+packet is encrypted with the session key.  See 2.7 Packet Padding
+Generation for more information about padding on special packets.
+
+The difference from channel message processing is that server or router
+en route never decrypts the actual private message, as it does not
+have the key to do that.  Thus, when sending packets between router
+the processing is same as in any other case as well; the packet's header
+and padding is protected by the session key and the data area is not
+touched and is not re-encrypted.
+
+The true receiver of the private message is able to decrypt the private
+message as it shares the key with the sender of the message.
+
+
+.ti 0
+2.6 Packet MAC Generation
+
+Data integrity of a packet is protected by including a message
+authentication code (MAC) at the end of the packet.  The MAC is computed
+from shared secret MAC key, that is established by the SILC Key Exchange
+protocol, from packet sequence number, and from the encrypted packet
+data.  The MAC is always computed after packet is encrypted.  This is
+so called Encrypt-Then-MAC order; packet is first encrypted, then MAC
+is computed from the encrypted data.
+
+The MAC is computed from entire packet.  Every bit of data in the packet,
+including SILC Packet Header is used in the MAC computing.  This way
+the entire packet becomes authenticated.
+
+Hence, packet's MAC generation is as follows:
+
+  mac = MAC(key, sequence number | Encrypted SILC packet)
+
+The MAC key is negotiated during the SKE protocol.  The sequence number
+is a 32 bit MSB first value starting from zero for first packet and
+increasing for subsequent packets, finally wrapping after 2^32 packets.
+The value is never reset, not even after rekey has been performed.
+However, rekey MUST be performed before the sequence number wraps
+and repeats from zero.  Note that the sequence number is incremented only
+when MAC is computed for a packet.  If packet is not encrypted and MAC is
+not computed then the sequence number is not incremented.  Hence, the
+sequence number is zero for the very first encrypted packet.
+
+See [SILC1] for defined and allowed MAC algorithms.
+
+
+.ti 0
+2.7 Packet Padding Generation
+
+Padding is needed in the packet because the packet is encrypted.  It
+always MUST be multiple by eight (8) or multiple by the block size
+of the cipher, which ever is larger.  The padding is always encrypted.
+
+For normal packets the padding is added after the SILC Packet Header
+and between the Data Payload area.  The padding for normal packets
+may be calculated as follows:
+
+.in 6
+padding_length = 16 - (packet_length mod block_size)
+if (padding_length < 8)
+  padding_length += block_size
+.in 3
+
+The `block_size' is the block size of the cipher.  The maximum padding
+length is 128 bytes, and minimum is 8 bytes.  For example, packets that
+include a passphrase or a password for authentication purposes SHOULD
+pad the packet up to the maximum padding length.  The maximum padding
+is calculated as follows:
+
+.in 6
+padding_length = 128 - (packet_length mod block_size)
+.in 3
+
+For special packets the padding calculation is different as special
+packets may be encrypted differently.  In these cases the encrypted
+data area MUST already be multiple by the block size thus in this case
+the padding is calculated only for SILC Packet Header, not for any
+other area of the packet.  The same algorithm works in this case as
+well, except that the `packet length' is now the SILC Packet Header
+length.
+
+The padding MUST be random data, preferably, generated by
+cryptographically strong random number generator for each packet
+separately.
+
+
+.ti 0
+2.8 Packet Compression
+
+SILC Packets MAY be compressed.  In this case the data payload area
+is compressed and all other areas of the packet MUST remain as they
+are.  After compression is performed for the data area, the length
+field of Packet Header MUST be set to the compressed length of the
+data.
+
+The compression MUST always be applied before encryption.  When
+the packet is received and decrypted the data area MUST be decompressed.
+Note that the true sender of the packet MUST apply the compression and
+the true receiver of the packet MUST apply the decompression.  Any
+server or router en route SHOULD NOT decompress the packet.
+
+
+.ti 0
+2.9 Packet Sending
+
+The sender of the packet MUST assemble the SILC Packet Header with
+correct values.  It MUST set the Source ID of the header as its own
+ID, unless it is forwarding the packet.  It MUST also set the Destination
+ID of the header to the true destination.  If the destination is client
+it will be Client ID, if it is server it will be Server ID and if it is
+channel it will be Channel ID.
+
+If the sender wants to compress the packet it MUST apply the
+compression now.  Sender MUST also compute the padding as described
+in above sections.  Then sender MUST encrypt the packet as has been
+described in above sections according whether the packet is normal
+packet or special packet.  Then sender MUST compute the MAC of the
+packet.  The computed MAC MUST NOT be encrypted.
+
+
+.ti 0
+2.10 Packet Reception
+
+On packet reception the receiver MUST check that all fields in the
+SILC Packet Header are valid.  It MUST check the flags of the
+header and act accordingly.  It MUST also check the MAC of the packet
+and if it is to be failed the packet MUST be discarded.  Also if the
+header of the packet includes any bad fields the packet MUST be
+discarded.
+
+See above sections on the decryption process of the received packet.
+
+The receiver MUST also check that the ID's in the header are valid
+ID's.  Unsupported ID types or malformed ID's MUST cause packet
+rejection.  The padding on the reception is always ignored.
+
+The receiver MUST also check the packet type and start parsing the
+packet according to the type.  However, note the above sections on
+special packet types and their parsing.
+
+
+.ti 0
+2.11 Packet Routing
+
+Routers are the primary entities in the SILC network that takes care
+of packet routing.  However, normal servers routes packets as well, for
+example, when they are routing channel message to the local clients.
+Routing is quite simple as every packet tells the true origin and the
+true destination of the packet.
+
+It is still RECOMMENDED for routers that has several routing connections
+to create route cache for those destinations that has faster route than
+the router's primary route.  This information is available for the router
+when other router connects to the router.  The connecting party then
+sends all of its locally connected clients, servers and channels.  These
+informations helps to create the route cache.  Also, when new channels
+are created to a cell its information is broadcasted to all routers
+in the network.  Channel ID's are based on router's ID thus it is easy
+to create route cache based on these informations.  If faster route for
+destination does not exist in router's route cache the packet MUST be
+routed to the primary route (default route).
+
+However, there are some issues when routing channel messages to group
+of users.  Routers are responsible of routing the channel message to
+other routers, local servers and local clients as well.  Routers MUST
+send the channel message to only one router in the network, preferably
+to the shortest route to reach the channel users.  The message can be
+routed into either upstream or downstream.  After the message is sent
+to a router in the network it MUST NOT be sent to any other router in
+either same route or other route.  The message MUST NOT be routed to
+the router it came from.
+
+When routing for example private messages they should be routed to the
+shortest route always to reach the destination client as fast as possible.
+
+For server which receives a packet to be routed to an entity that is
+indirectly connected to the sender, the server MUST check whether that
+particular packet type is allowed to be routed to that destination.  Not
+all packets may be sent by some odd entity to for example a local client,
+or to some remote server or router, that is indirectly connected to the
+sender.  See section 2.3 SILC Packet Types and paragraph about indirectly
+connected entities and sending packets to them.  That section defines the
+packets that may be sent to indirectly connected entities.  When a server
+or a router receives a packet that may be sent to indirectly connected
+entity and it is destined to other entity except that server, it MUST
+route it further either to shortest route or to the primary route to reach
+that destination.
+
+Routers form a ring in the SILC network.  However, routers may have other
+direct connections to other routers in the network too.  This can cause
+interesting routing problems in the network.  Since the network is a ring,
+the packets usually should be routed into clock-wise direction, or if it
+cannot be used then always counter clock-wise (primary route) direction.
+Problems may arise when a faster direct route exists and router is routing
+a channel message.  Currently channel messages must be routed either
+in upstream or downstream, they cannot be routed to other direct routes.
+The SILC protocol should have a shortest path discovery protocol, and some
+existing routing protocol, that can handle a ring network with other
+direct routes inside the ring (so called hybrid ring-mesh topology),
+MAY be defined to be used with the SILC protocol.  Additional
+specifications MAY be written on the subject to permeate this
+specification.
+
+
+.ti 0
+2.12 Packet Broadcasting
+
+SILC packets MAY be broadcasted in SILC network.  However, only router
+server may send or receive broadcast packets.  Client and normal server
+MUST NOT send broadcast packets and they MUST ignore broadcast packets
+if they receive them.  Broadcast packets are sent by setting Broadcast
+flag to the SILC packet header.
+
+Broadcasting packets means that the packet is sent to all routers in
+the SILC network, except to the router that sent the packet.  The router
+receiving broadcast packet MUST send the packet to its primary route.
+The fact that SILC routers may have several router connections can
+cause problems, such as race conditions inside the SILC network, if
+care is not taken when broadcasting packets.  Router MUST NOT send
+the broadcast packet to any other route except to its primary route.
+
+If the primary route of the router is the original sender of the packet
+the packet MUST NOT be sent to the primary route.  This may happen
+if router has several router connections and some other router uses
+the router as its primary route.
+
+Routers use broadcast packets to broadcast for example information
+about newly registered clients, servers, channels etc. so that all the
+routers may keep these informations up to date.
+
+
+.ti 0
+3 Security Considerations
+
+Security is central to the design of this protocol, and these security
+considerations permeate the specification.  Common security considerations
+such as keeping private keys truly private and using adequate lengths for
+symmetric and asymmetric keys must be followed in order to maintain the
+security of this protocol.
+
+
+.ti 0
+4 References
+
+[SILC1]      Riikonen, P., "Secure Internet Live Conferencing (SILC),
+             Protocol Specification", Internet Draft, May 2002.
+
+[SILC3]      Riikonen, P., "SILC Key Exchange and Authentication
+             Protocols", Internet Draft, May 2002.
+
+[SILC4]      Riikonen, P., "SILC Commands", Internet Draft, May 2002.
+
+[IRC]        Oikarinen, J., and Reed D., "Internet Relay Chat Protocol",
+             RFC 1459, May 1993.
+
+[IRC-ARCH]   Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+             April 2000.
+
+[IRC-CHAN]   Kalt, C., "Internet Relay Chat: Channel Management", RFC
+             2811, April 2000.
+
+[IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+             2812, April 2000.
+
+[IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+             2813, April 2000.
+
+[SSH-TRANS]  Ylonen, T., et al, "SSH Transport Layer Protocol",
+             Internet Draft.
+
+[PGP]        Callas, J., et al, "OpenPGP Message Format", RFC 2440,
+             November 1998.
+
+[SPKI]       Ellison C., et al, "SPKI Certificate Theory", RFC 2693,
+             September 1999.
+
+[PKIX-Part1] Housley, R., et al, "Internet X.509 Public Key
+             Infrastructure, Certificate and CRL Profile", RFC 2459,
+             January 1999.
+
+[Schneier]   Schneier, B., "Applied Cryptography Second Edition",
+             John Wiley & Sons, New York, NY, 1996.
+
+[Menezes]    Menezes, A., et al, "Handbook of Applied Cryptography",
+             CRC Press 1997.
+
+[OAKLEY]     Orman, H., "The OAKLEY Key Determination Protocol",
+             RFC 2412, November 1998.
+
+[ISAKMP]     Maughan D., et al, "Internet Security Association and
+             Key Management Protocol (ISAKMP)", RFC 2408, November
+             1998.
+
+[IKE]        Harkins D., and Carrel D., "The Internet Key Exchange
+             (IKE)", RFC 2409, November 1998.
+
+[HMAC]       Krawczyk, H., "HMAC: Keyed-Hashing for Message
+             Authentication", RFC 2104, February 1997.
+
+[PKCS1]      Kalinski, B., and Staddon, J., "PKCS #1 RSA Cryptography
+             Specifications, Version 2.0", RFC 2437, October 1998.
+
+[RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
+             Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+[SFTP]       Ylonen T., and Lehtinen S., "Secure Shell File Transfer
+             Protocol", Internet Draft, March 2001.
+
+[RFC3629]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 3629, November 2003.
+
+
+.ti 0
+5 Author's Address
+
+.nf
+Pekka Riikonen
+Snellmaninkatu 34 A 15
+70100 Kuopio
+Finland
+
+EMail: priikone@iki.fi
+
+
+.ti 0
+6 Full Copyright Statement
+
+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.
index 5aa308b638d7a3f54da4b5ba495a9cf9d2183979..082e7ac24dc12834475d98d1c3cfc64c304d8e58 100644 (file)
@@ -8,7 +8,7 @@
 .ds RF FORMFEED[Page %]
 .ds CF
 .ds LH Internet Draft
-.ds RH 11 August 2003
+.ds RH 11 February 2004
 .ds CH
 .na
 .hy 0
@@ -16,8 +16,8 @@
 .nf
 Network Working Group                                        P. Riikonen
 Internet-Draft
-draft-riikonen-silc-spec-08.txt                           11 August 2003
-Expires: 11 February 2004
+draft-riikonen-silc-spec-08.txt                         11 February 2004
+Expires: 11 August 2004
 
 .in 3
 
@@ -73,7 +73,7 @@ Table of Contents
 1 Introduction ..................................................  3
   1.1 Requirements Terminology ..................................  4
 2 SILC Concepts .................................................  4
-  2.1 SILC Network Topology .....................................  4
+  2.1 SILC Network Topology .....................................  5
   2.2 Communication Inside a Cell ...............................  6
   2.3 Communication in the Network ..............................  7
   2.4 Channel Communication .....................................  7
@@ -89,7 +89,7 @@ Table of Contents
       3.3.1 Router's Local ID List .............................. 13
       3.3.2 Router's Global ID List ............................. 14
       3.3.3 Router's Server ID .................................. 14
-  3.4 Channels .................................................. 14
+  3.4 Channels .................................................. 15
       3.4.1 Channel ID .......................................... 16
   3.5 Operators ................................................. 16
   3.6 SILC Commands ............................................. 17
@@ -111,28 +111,32 @@ Table of Contents
       3.10.3 Hash Functions ..................................... 27
       3.10.4 MAC Algorithms ..................................... 27
       3.10.5 Compression Algorithms ............................. 28
-  3.11 SILC Public Key .......................................... 29
+  3.11 SILC Public Key .......................................... 28
   3.12 SILC Version Detection ................................... 31
-  3.13 Backup Routers ........................................... 31
-      3.13.1 Switching to Backup Router ......................... 33
-      3.13.2 Resuming Primary Router ............................ 34
-4 SILC Procedures ............................................... 36
-  4.1 Creating Client Connection ................................ 37
-  4.2 Creating Server Connection ................................ 38
-      4.2.1 Announcing Clients, Channels and Servers ............ 39
-  4.3 Joining to a Channel ...................................... 40
-  4.4 Channel Key Generation .................................... 41
-  4.5 Private Message Sending and Reception ..................... 42
-  4.6 Private Message Key Generation ............................ 42
-  4.7 Channel Message Sending and Reception ..................... 43
-  4.8 Session Key Regeneration .................................. 44
-  4.9 Command Sending and Reception ............................. 44
-  4.10 Closing Connection ....................................... 45
-  4.11 Detaching and Resuming a Session ......................... 46
-5 Security Considerations ....................................... 47
-6 References .................................................... 48
-7 Author's Address .............................................. 50
-8 Full Copyright Statement ...................................... 50
+  3.13 UTF-8 Strings in SILC .................................... 31
+      3.13.1 UTF-8 Identifier Strings ........................... 32
+  3.14 Backup Routers ........................................... 33
+      3.14.1 Switching to Backup Router ......................... 35
+      3.14.2 Resuming Primary Router ............................ 36
+4 SILC Procedures ............................................... 38
+  4.1 Creating Client Connection ................................ 38
+  4.2 Creating Server Connection ................................ 40
+      4.2.1 Announcing Clients, Channels and Servers ............ 40
+  4.3 Joining to a Channel ...................................... 42
+  4.4 Channel Key Generation .................................... 43
+  4.5 Private Message Sending and Reception ..................... 44
+  4.6 Private Message Key Generation ............................ 44
+  4.7 Channel Message Sending and Reception ..................... 45
+  4.8 Session Key Regeneration .................................. 46
+  4.9 Command Sending and Reception ............................. 46
+  4.10 Closing Connection ....................................... 47
+  4.11 Detaching and Resuming a Session ......................... 48
+5 Security Considerations ....................................... 49
+6 References .................................................... 50
+7 Author's Address .............................................. 52
+Appendix A ...................................................... 52
+Appendix B ...................................................... 54
+Full Copyright Statement ........................................ 54
 
 .ti 0
 List of Figures
@@ -212,6 +216,7 @@ concepts are introduced to make the topology of the SILC network
 clear.
 
 
+
 .ti 0
 2.1 SILC Network Topology
 
@@ -466,8 +471,8 @@ host names to be used along with the nicknames on user interface to
 identify specific users when sending messages.  This feature of SILC
 makes IRC style nickname-wars obsolete as no one owns their nickname;
 there can always be someone else with the same nickname.  Also, any kind
-of nickname registering service becomes obsolete.  The maximum length of
-nickname is 128 bytes.
+of nickname registering service becomes obsolete.  See the section 3.13.1
+for more information about nicknames.
 
 
 .ti 0
@@ -502,11 +507,13 @@ o Random number or counter - Random number to further
   possible to have 2^8 same nicknames from the same
   server IP address.
 
-o MD5 hash - MD5 hash value of the lowercase nickname is
+o MD5 hash - MD5 hash value of the case folded nickname is
   truncated taking 88 bits from the start of the hash value.
   This hash value is used to search the user's Client ID
-  from the ID lists.  Note that the nickname MUST be in
-  lowercase format.
+  from the ID lists.  Note that the nickname MUST be prepared
+  using the stringprep [RFC3454] profile described in the
+  Appendix A before computing the MD5 hash.  See also the
+  section 3.13.1 for more information.
 
 .in 3
 Collisions could occur when more than 2^8 clients using same nickname
@@ -574,7 +581,6 @@ client list        - All clients in server
    o Receiving key
    o Public key
 
-
 channel list       - All channels in server
    o Channel name
    o Channel ID
@@ -584,7 +590,6 @@ channel list       - All channels in server
 .in 3
 
 
-
 .ti 0
 3.2.2 Server ID
 
@@ -638,7 +643,6 @@ Server on network above privileged ports (>1023) SHOULD NOT be trusted
 as they could have been set up by untrusted party.
 
 
-
 .ti 0
 3.3 Router
 
@@ -738,6 +742,8 @@ normal servers same types of IDs applies for routers as well.  See
 section 3.2.2 Server ID.
 
 
+
+
 .ti 0
 3.4 Channels
 
@@ -754,14 +760,12 @@ channel.
 
 Channel names are unique although the real uniqueness comes from 64 bit
 Channel ID.  However, channel names are still unique and no two global
-channels with same name may exist.  The channel name is a string of
-maximum length of 256 bytes.  Channel names MUST NOT contain any
-whitespaces (`  '), any non-printable ASCII characters, commas (`,')
-and wildcard characters.
+channels with same name may exist.  See the section 3.13.1 for more
+information about channel names.
 
-Channels can have operators that can administrate the channel and
-operate all of its modes.  The following operators on channel exist on
-the SILC network.
+Channels can have operators that can administrate the channel and operate
+all of its modes.  The following operators on channel exist on the
+SILC network.
 
 .in 6
 o Channel founder - When channel is created the joining client becomes
@@ -1082,7 +1086,7 @@ to connect to server without explicit authentication.  Servers are
 REQUIRED to use authentication protocol when connecting.  The
 authentication may be based on passphrase (pre-shared secret) or public
 key based on digital signatures.  All passphrases sent in SILC protocol
-MUST be UTF-8 [RFC2279] encoded. The connection authentication protocol
+MUST be UTF-8 [RFC3629] encoded. The connection authentication protocol
 is described in detail in [SILC3].
 
 
@@ -1402,7 +1406,6 @@ md5              MD5, length = 16        (RECOMMENDED)
 .in 3
 
 
-
 .ti 0
 3.10.4 MAC Algorithms
 
@@ -1621,7 +1624,86 @@ SILC-1.2-2.4.5 Vendor Limited
 
 
 .ti 0
-3.13 Backup Routers
+3.13 UTF-8 Strings in SILC
+
+By default all strings that are sent in SILC protocol MUST be UTF-8
+[RFC3269] encoded, unless otherwise defined.  This means that any string
+sent inside for example, command, command reply, notify or any packet
+payload is UTF-8 encoded.  Also nicknames, channel names, server names,
+and hostnames are UTF-8 encoded.  This definition does not affect
+messages sent in SILC, as the Message Payload provides its own mechanism
+to indicate whether a message is UTF-8 text message, data message, which
+may use its own character encoding, or pure binary message [SILC2].
+
+Certain limitations are imposed on the UTF-8 encoded strings in SILC.
+The UTF-8 encoded strings MUST NOT include any characters that are
+marked in the Unicode standard as control codes, noncharacters,
+reserved or private range characters, or any other illegal Unicode
+characters.  Also the BOM (Byte-Order Mark) MUST NOT be used as byte
+order signature in UTF-8 encoded strings.  A string containing these
+characters MUST be treated as malformed UTF-8 encoding.
+
+The Unicode standard defines that malformed sequences shall be signalled
+by replacing the sequence with a replacement character.  Even though,
+in case of SILC these strings may not be malformed UTF-8 encodings
+they MUST be treated as malformed strings.  Implementation MAY use
+a replacement character, however, the character Unicode standard defines
+MUST NOT be used, but another character must be chosen.  It is, however,
+RECOMMENDED that an error is returned instead of using replacement
+character if it is possible.  For example, when setting a nickname
+with SILC_COMMAND_NICK command, implementation is able to send error
+indication back to the command sender.  It must be noted that on server
+implementation if a character sequence is merely outside of current
+character subset, but is otherwise valid character, it MUST NOT be
+replaced by a replacement character.
+
+On user interface where UTF-8 strings are displayed the implementation
+is RECOMMENDED to escape any character that it is unable to render
+properly.  The escaping may be done for example as described in
+[RFC2253].  The escaping makes it possible to retrieve the original
+UTF-8 encoding.  Alternatively, a replacement character may be used
+if it does not cause practical problems to the implementation.
+
+
+.ti 0
+3.13.1 UTF-8 Identifier Strings
+
+Identifier strings are special strings in SILC protocol that require
+more careful processing, than the general UTF-8 strings described in the
+previous section.  These strings include the nicknames, channel names,
+server names, hostnames and some other identifier strings.  These strings
+are prepared using the stringprep [RFC3454] standard.  The Appendix A
+defines the stringprep profile for SILC identifier strings and conforming
+implementation MUST use the profile to prepare any identifier string.
+
+The stringprep profile describes how identifier strings are prepared,
+what characters they may include, and which characters are prohibited.
+Identifier strings with prohibited characters MUST be treated as
+malformed strings.
+
+Because of the profile the identifier strings in SILC may generally
+include only letters, numbers, most punctuation characters, and some
+other characters.  For practical reasons most symbol characters and
+many other special characters are prohibited.  All identifier strings
+are case folded and comparing the identifier strings MUST be done as
+caseless matching.  Also, identifier strings may not include any
+commas (','), '@', '!' or any wildcard characters, as defined in the
+stringprep profile in Appendix A.
+
+In general, the identifier strings does not have a maximum length.
+However, the length of a nickname string MUST NOT exceed 128 bytes, and
+the length of a channel name string MUST NOT exceed 256 bytes.  Since
+these strings are UTF-8 encoded the length of one character may be
+longer than one byte.  This means that the character length of these
+strings may be shorter than the maximum length of the string in bytes.
+The minimum length of an identifier string MUST be at least one character,
+which may be one byte or more in length.  Implementation MAY limit the
+maximum length of an identifier string, with exception of the nickname
+and channel name strings which has the explicit length definition.
+
+
+.ti 0
+3.14 Backup Routers
 
 Backup routers may exist in the cell in addition to the primary router.
 However, they must not be active routers or act as routers in the cell.
@@ -1702,7 +1784,7 @@ router as described above.
 
 
 .ti 0
-3.13.1 Switching to Backup Router
+3.14.1 Switching to Backup Router
 
 When the primary router of the cell becomes unresponsive, for example
 by sending EOF to the connection, all the parties of this protocol MUST
@@ -1750,7 +1832,7 @@ and Servers.
 
 
 .ti 0
-3.13.2 Resuming Primary Router
+3.14.2 Resuming Primary Router
 
 Usually the primary router is unresponsive only a short period of time
 and it is intended that the original router of the cell will resume
@@ -1869,8 +1951,6 @@ so on.  The references [SILC2], [SILC3] and [SILC4] permeate this
 section's definitions.
 
 
-
-
 .ti 0
 4.1 Creating Client Connection
 
@@ -1940,6 +2020,8 @@ is watching for the nickname this new client has, and send the
 SILC_NOTIFY_TYPE_WATCH to the watcher.
 
 
+
+
 .ti 0
 4.2 Creating Server Connection
 
@@ -2009,7 +2091,7 @@ MUST be announced by compiling a list of Notify Payloads with the
 SILC_NOTIFY_TOPIC_SET notify type into the SILC_PACKET_NOTIFY packet.
 Also, channel's invite and ban lists MUST be announced by compiling list
 of Notify Payloads with the SILC_NOTIFY_TYPE_INVITE and
-SILC_NOTIFY_TYPE_BAN notify types, respectively, into the 
+SILC_NOTIFY_TYPE_BAN notify types, respectively, into the
 SILC_PACKET_NOTIFY packet.
 
 The router which receives these lists MUST process them and broadcast
@@ -2181,37 +2263,44 @@ process.
 4.6 Private Message Key Generation
 
 Private message MAY be protected with a key generated by the client.
-The key may be generated and sent to the other client by sending packet
-SILC_PACKET_PRIVATE_MESSAGE_KEY which travels through the network
-and is secured by session keys.  After that the private message key
-is used in the private message communication between those clients.
-The key sent inside the payload SHOULD be randomly generated.  This
-packet MUST NOT be used to send pre-shared keys.
-
-Another choice is to entirely use keys that are not sent through
-the SILC network at all.  This significantly adds security.  This key
-could be a pre-shared key that is known by both of the clients.  Both
-agree about using the key and start sending packets that indicate
-that the private message is secured using private message key.  In
-case of pre-shared keys (static keys) the IV used in encryption SHOULD
-be chosen randomly.
-
-It is also possible to negotiate fresh key material by performing
-Key Agreement.  The SILC_PACKET_KEY_AGREEMENT packet MAY be used to
-negotiate the fresh key material.  In this case the resulting key
-material is used to secure the private messages.  Also, the IV used
-in encryption is used as defined in [SILC3], unless otherwise stated
-by the encryption mode used.  By performing Key Agreement the clients
-may negotiate the cipher and HMAC to be used in the private message
-encryption and to negotiate additional security parameters.
+One way to generate private message key is to use static or pre-shared
+keys in the client implementation.  Client that wants to indicate other
+client on the network that a private message key should be set, the
+client MAY send SILC_PACKET_PRIVATE_MESSAGE_KEY packet to indicate this.
+The actual key material has to be transferred outside the SILC network,
+or it has to be pre-shared key.  The client receiving this packet knows
+that the sender wishes to use private message key in private message
+communication.  In case of static or pre-shared keys the IV used in
+the encryption SHOULD be chosen randomly.  Sending the
+SILC_PACKET_PRIVATE_MESSAGE_KEY is not mandatory, and clients may
+naturally agree to use a key without sending the packet.
+
+Another choice to use private message keys is to negotiate fresh key
+material by performing the Key Agreement.  The SILC_PACKET_KEY_AGREEMENT
+packet MAY be used to negotiate the fresh key material.  In this case
+the resulting key material is used to secure the private messages.
+Also, the IV used in encryption is used as defined in [SILC3], unless
+otherwise stated by the encryption mode used.  By performing Key
+Agreement the clients can also negotiate the cipher and HMAC to be used
+in the private message encryption and to negotiate additional security
+parameters.  The actual Key Agreement [SILC2] is performed by executing
+the SILC Key Exchange protocol [SILC3], peer to peer.  Because of NAT
+devices in the network, it might be impossible to perform the Key
+Agreement.  In this case using static or pre-shared key and sending the
+SILC_PACKET_PRIVATE_MESSAGE_KEY to indicate the use of a private message
+key is a working alternative.
 
 If the key is pre-shared key or other key material not generated by
 Key Agreement, then the key material SHOULD be processed as defined
-in [SILC3].  The hash function to be used SHOULD be SHA1.  In the
-processing, however, the HASH, as defined in [SILC3] MUST be ignored.
-After processing the key material it is employed as defined in [SILC3].
-In this case also, implementations SHOULD use the SILC protocol's
-mandatory cipher and HMAC in private message encryption.
+in [SILC3].  In the processing, however, the HASH, as defined in [SILC3]
+MUST be ignored.  After processing the key material it is employed as
+defined in [SILC3].  If the SILC_PACKET_PRIVATE_MESSAGE_KEY was sent,
+then it defines the cipher and HMAC to be used.  The hash algorithm to be
+used in the key material processing is the one that HMAC algorithm is
+defined to use.  If the SILC_PACKET_PRIVATE_MESSAGE_KEY was not sent at
+all, then the hash algorithm to be used SHOULD be SHA1.  In this case
+also, implementations SHOULD use the SILC protocol's mandatory cipher
+and HMAC in private message encryption.
 
 
 .ti 0
@@ -2330,8 +2419,6 @@ SILC_NOTIFY_TYPE_WATCH to the watcher, unless the client which left
 the network has the SILC_UMODE_REJECT_WATCHING user mode set.
 
 
-
-
 .ti 0
 4.11 Detaching and Resuming a Session
 
@@ -2539,8 +2626,8 @@ should have a forum to discuss the cell management issues.
 [RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.
 
-[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
-             10646", RFC 2279, January 1998.
+[RFC3629]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 3629, November 2003.
 
 [RFC1321]    Rivest R., "The MD5 Message-Digest Algorithm", RFC 1321,
              April 1992.
@@ -2555,6 +2642,9 @@ should have a forum to discuss the cell management issues.
              (v3): UTF-8 String Representation of Distinguished Names",
              RFC 2253, December 1997.
 
+[RFC3454]    Hoffman, P., et al., "Preparation of Internationalized
+             Strings ("stringprep")", RFC 3454, December 2002.
+
 
 .ti 0
 7 Author's Address
@@ -2569,7 +2659,98 @@ EMail: priikone@iki.fi
 
 
 .ti 0
-8 Full Copyright Statement
+Appendix A
+
+This appendix defines the stringprep [RFC3454] profile for string
+identifiers in SILC protocol.  Compliant implementation MUST use this
+profile to prepare the identifier strings in the SILC protocol.  The
+profile defines the following as required by [RFC3454].
+
+- Intended applicability of the profile:  the following identifiers in
+  the SILC Protocol;  nicknames, channel names, usernames, server names,
+  hostnames, service names, algorithm names and other security property
+  names [SILC3], and SILC Public Key name.
+
+- The character repertoire that is the input and output to
+  stringprep:  Unicode 3.2 with the list of unassigned code points
+  being the Table A.1, as defined in [RFC3454].
+
+- The mapping tables used:  the following tables are used, in order,
+  as defined in [RFC3454].
+
+    Table B.1
+    Table B.2
+
+  The mandatory case folding is done using the Table B.2 which includes
+  the characters for the normalization form KC.
+
+- The Unicode normalization used:  the Unicode normalization form
+  KC is used, as defined in [RFC3454].
+
+- The prohibited characters as output:  the following tables are used
+  to prohibit characters, as defined in [RFC3454];
+
+    Table C.1.1
+    Table C.1.2
+    Table C.2.1
+    Table C.2.2
+    Table C.3
+    Table C.4
+    Table C.5
+    Table C.6
+    Table C.7
+    Table C.8
+    Table C.9
+
+- Additional prohibited characters as output:  in addition, the following
+  tables are used to prohibit characters, as defined in this document;
+
+    Appendix B
+
+- The bidirectional string testing used:  bidirectional string testing
+  is ignored in this profile.
+
+This profile is to be maintained in the IANA registry for stringprep
+profiles.  The name of this profile is "silc-identifier-prep" and this
+document defines the profile.  This document defines the first version of
+this profile.
+
+
+.ti 0
+Appendix B
+
+This appendix defines additional prohibited characters in the identifier
+strings as defined in the stringprep profile in Appendix A.  Note that
+the prohibited character tables listed in the Appendix A may include some
+of the same characters listed in this appendix as well.
+
+Reserved US-ASCII characters
+0021 002A 002C 003F 0040
+
+Symbol characters and other symbol like characters
+00A2-00A9 00AC 00AE 00AF 00B0 00B1 00B4 00B6 00B8 00D7 00F7
+02C2-02C5 02D2-02FF 0374 0375 0384 0385 03F6 0482 060E 060F
+06E9 06FD 06FE 09F2 09F3 09FA 0AF1 0B70 0BF3-0BFA 0E3F
+0F01-0F03 0F13-0F17 0F1A-0F1F 0F34 0F36 0F38 0FBE 0FBF
+0FC0-0FC5 0FC7-0FCF 17DB 1940 19E0-19FF 1FBD 1FBF-1FC1
+1FCD-1FCF 1FDD-1FDF 1FED-1FEF 1FFD 1FFE 2044 2052 207A-207C
+208A-208C 20A0-20B1 2100-214F 2150-218F 2190-21FF 2200-22FF
+2300-23FF 2400-243F 2440-245F 2460-24FF 2500-257F 2580-259F
+25A0-25FF 2600-26FF 2700-27BF 27C0-27EF 27F0-27FF 2800-28FF
+2900-297F 2980-29FF 2A00-2AFF 2B00-2BFF 2E9A 2EF4-2EFF
+2FF0-2FFF 303B-303D 3040 3095-3098 309F-30A0 30FF-3104
+312D-3130 318F 31B8-31FF 321D-321F 3244-325F 327C-327E
+32B1-32BF 32CC-32CF 32FF 3377-337A 33DE-33DF 33FF 4DB6-4DFF
+9FA6-9FFF A48D-A48F A4A2-A4A3 A4B4 A4C1 A4C5 A4C7-ABFF
+D7A4-D7FF FA2E-FAFF FFE0-FFEE FFFC 10000-1007F 10080-100FF
+10100-1013F 1D000-1D0FF 1D100-1D1FF 1D300-1D35F 1D400-1D7FF
+
+Other characters
+E0100-E01EF
+
+
+.ti 0
+Full Copyright Statement
 
 Copyright (C) The Internet Society (2003). All Rights Reserved.
 
diff --git a/doc/draft-riikonen-silc-spec-09.nroff b/doc/draft-riikonen-silc-spec-09.nroff
new file mode 100644 (file)
index 0000000..d1c3dd5
--- /dev/null
@@ -0,0 +1,2848 @@
+.pl 10.0i
+.po 0
+.ll 7.2i
+.lt 7.2i
+.nr LL 7.2i
+.nr LT 7.2i
+.ds LF Riikonen
+.ds RF FORMFEED[Page %]
+.ds CF
+.ds LH Internet Draft
+.ds RH 11 February 2004
+.ds CH
+.na
+.hy 0
+.in 0
+.nf
+Network Working Group                                        P. Riikonen
+Internet-Draft
+draft-riikonen-silc-spec-09.txt                         XX
+Expires: XXX
+
+.in 3
+
+.ce 3
+Secure Internet Live Conferencing (SILC),
+Protocol Specification
+<draft-riikonen-silc-spec-09.txt>
+
+.ti 0
+Status of this Memo
+
+This document is an Internet-Draft and is in full conformance with
+all provisions of Section 10 of RFC 2026.  Internet-Drafts are
+working documents of the Internet Engineering Task Force (IETF), its
+areas, and its working groups.  Note that other groups may also
+distribute working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six months
+and may be updated, replaced, or obsoleted by other documents at any
+time.  It is inappropriate to use Internet-Drafts as reference
+material or to cite them other than as "work in progress."
+
+The list of current Internet-Drafts can be accessed at
+http://www.ietf.org/ietf/1id-abstracts.txt
+
+The list of Internet-Draft Shadow Directories can be accessed at
+http://www.ietf.org/shadow.html
+
+The distribution of this memo is unlimited.
+
+
+.ti 0
+Abstract
+
+This memo describes a Secure Internet Live Conferencing (SILC)
+protocol which provides secure conferencing services over insecure
+network channel.  SILC provides advanced and feature rich conferencing
+services with security as main design principal.  Strong cryptographic
+methods are used to protect SILC packets inside the SILC network.
+Three other specifications relates very closely to this memo;
+SILC Packet Protocol [SILC2], SILC Key Exchange and Authentication
+Protocols [SILC3] and SILC Commands [SILC4].
+
+
+
+
+
+
+.ti 0
+Table of Contents
+
+.nf
+1 Introduction ..................................................  3
+  1.1 Requirements Terminology ..................................  4
+2 SILC Concepts .................................................  4
+  2.1 SILC Network Topology .....................................  5
+  2.2 Communication Inside a Cell ...............................  6
+  2.3 Communication in the Network ..............................  7
+  2.4 Channel Communication .....................................  7
+  2.5 Router Connections ........................................  8
+3 SILC Specification ............................................  9
+  3.1 Client ....................................................  9
+      3.1.1 Client ID ...........................................  9
+  3.2 Server .................................................... 10
+      3.2.1 Server's Local ID List .............................. 11
+      3.2.2 Server ID ........................................... 12
+      3.2.3 SILC Server Ports ................................... 12
+  3.3 Router .................................................... 13
+      3.3.1 Router's Local ID List .............................. 13
+      3.3.2 Router's Global ID List ............................. 14
+      3.3.3 Router's Server ID .................................. 14
+  3.4 Channels .................................................. 15
+      3.4.1 Channel ID .......................................... 16
+  3.5 Operators ................................................. 16
+  3.6 SILC Commands ............................................. 17
+  3.7 SILC Packets .............................................. 17
+  3.8 Packet Encryption ......................................... 17
+      3.8.1 Determination of the Source and the Destination ..... 18
+      3.8.2 Client To Client .................................... 19
+      3.8.3 Client To Channel ................................... 20
+      3.8.4 Server To Server .................................... 21
+  3.9 Key Exchange And Authentication ........................... 21
+      3.9.1 Authentication Payload .............................. 21
+  3.10 Algorithms ............................................... 23
+      3.10.1 Ciphers ............................................ 23
+             3.10.1.1 CBC Mode .................................. 24
+             3.10.1.2 CTR Mode .................................. 24
+             3.10.1.3 Randomized CBC Mode ....................... 26
+      3.10.2 Public Key Algorithms .............................. 26
+             3.10.2.1 Multi-Precision Integers .................. 27
+      3.10.3 Hash Functions ..................................... 27
+      3.10.4 MAC Algorithms ..................................... 27
+      3.10.5 Compression Algorithms ............................. 28
+  3.11 SILC Public Key .......................................... 28
+  3.12 SILC Version Detection ................................... 31
+  3.13 UTF-8 Strings in SILC .................................... 31
+      3.13.1 UTF-8 Identifier Strings ........................... 32
+  3.14 Backup Routers ........................................... 33
+      3.14.1 Switching to Backup Router ......................... 35
+      3.14.2 Resuming Primary Router ............................ 36
+4 SILC Procedures ............................................... 38
+  4.1 Creating Client Connection ................................ 38
+  4.2 Creating Server Connection ................................ 40
+      4.2.1 Announcing Clients, Channels and Servers ............ 40
+  4.3 Joining to a Channel ...................................... 42
+  4.4 Channel Key Generation .................................... 43
+  4.5 Private Message Sending and Reception ..................... 44
+  4.6 Private Message Key Generation ............................ 44
+  4.7 Channel Message Sending and Reception ..................... 45
+  4.8 Session Key Regeneration .................................. 46
+  4.9 Command Sending and Reception ............................. 46
+  4.10 Closing Connection ....................................... 47
+  4.11 Detaching and Resuming a Session ......................... 48
+5 Security Considerations ....................................... 49
+6 References .................................................... 50
+7 Author's Address .............................................. 52
+Appendix A ...................................................... 52
+Appendix B ...................................................... 54
+Appendix C ...................................................... XXX
+Appendix D ...................................................... XXX
+Full Copyright Statement ........................................ XXX
+
+.ti 0
+List of Figures
+
+.nf
+Figure 1:  SILC Network Topology
+Figure 2:  Communication Inside cell
+Figure 3:  Communication Between Cells
+Figure 4:  Router Connections
+Figure 5:  SILC Public Key
+Figure 6:  Counter Block
+
+
+.ti 0
+1. Introduction
+
+This document describes a Secure Internet Live Conferencing (SILC)
+protocol which provides secure conferencing services over insecure
+network channel.  SILC can be used as a secure conferencing service
+that provides rich conferencing features.  Some of the SILC features
+are found in traditional chat protocols such as IRC [IRC] but many
+of the SILC features can also be found in Instant Message (IM) style
+protocols.  SILC combines features from both of these chat protocol
+styles, and can be implemented as either IRC-like system or IM-like
+system.  Some of the more advanced and secure features of the
+protocol are new to all conferencing protocols.  SILC also supports
+multimedia messages and can also be implemented as a video and audio
+conferencing system.
+
+Strong cryptographic methods are used to protect SILC packets inside
+the SILC network.  Three other specifications relates very closely
+to this memo; SILC Packet Protocol [SILC2], SILC Key Exchange and
+Authentication Protocols [SILC3] and SILC Commands [SILC4].
+
+The protocol uses extensively packets as conferencing protocol
+requires message and command sending.  The SILC Packet Protocol is
+described in [SILC2] and should be read to fully comprehend this
+document and protocol.  [SILC2] also describes the packet encryption
+and decryption in detail.  The SILC Packet Protocol provides secured
+and authenticated packets, and the protocol is designed to be compact.
+This makes SILC also suitable in environment of low bandwidth
+requirements such as mobile networks.  All packet payloads in SILC
+can be also compressed.
+
+The security of SILC protocol sessions are based on strong and secure
+key exchange protocol.  The SILC Key Exchange protocol is described
+in [SILC3] along with connection authentication protocol and should
+be read to fully comprehend this document and protocol.
+
+The SILC protocol has been developed to work on TCP/IP network
+protocol, although it could be made to work on other network protocols
+with only minor changes.  However, it is recommended that TCP/IP
+protocol is used under SILC protocol.  Typical implementation would
+be made in client-server model.
+
+
+.ti 0
+1.1 Requirements Terminology
+
+The keywords MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED,
+MAY, and OPTIONAL, when they appear in this document, are to be
+interpreted as described in [RFC2119].
+
+
+.ti 0
+2. SILC Concepts
+
+This section describes various SILC protocol concepts that forms the
+actual protocol, and in the end, the actual SILC network.  The mission
+of the protocol is to deliver messages from clients to other clients
+through routers and servers in secure manner.  The messages may also
+be delivered from one client to many clients forming a group, also
+known as a channel.
+
+This section does not focus to security issues.  Instead, basic network
+concepts are introduced to make the topology of the SILC network
+clear.
+
+
+
+.ti 0
+2.1 SILC Network Topology
+
+SILC network forms a ring as opposed to tree style network topology that
+conferencing protocols usually have.  The network has a cells which are
+constructed from a router and zero or more servers.  The servers are
+connected to the router in a star like network topology.  Routers in the
+network are connected to each other forming a ring.  The rationale for
+this is to have servers that can perform specific kind of tasks what
+other servers cannot perform.  This leads to two kinds of servers; normal
+SILC servers and SILC router servers.
+
+A difference between normal server and router server is that routers
+knows all global information and keep the global network state up to date.
+They also do the actual routing of the messages to the correct receiver
+between other cells.  Normal servers knows only local information and
+receive global information only when it is needed.  They do not need to
+keep the global network state up to date.  This makes the network faster
+and scalable as there are less servers that needs to maintain global
+network state.
+
+This, on the other hand, leads into a cellular like network, where
+routers are in the center of the cell and servers are connected to the
+router.
+
+The following diagram represents SILC network topology.
+
+.in 8
+.nf
+  ---- ---- ----         ---- ---- ----
+ | S8 | S5 | S4 |       | S7 | S5 | S6 |
+ ----- ---- -----       ----- ---- -----
+| S7 | S/R1 | S2 | --- | S8 | S/R2 | S4 |
+ ---- ------ ----       ---- ------ ----
+ | S6 | S3 | S1 |       | S1 | S3 | S2 |         ---- ----
+  ---- ---- ----         ---- ---- ----         | S3 | S1 |
+     Cell 1.   \\             Cell 2.  | \\____  ----- -----
+                |                     |        | S4 | S/R4 |
+    ---- ---- ----         ---- ---- ----       ---- ------
+   | S7 | S4 | S2 |       | S1 | S3 | S2 |      | S2 | S5 |
+   ----- ---- -----       ----- ---- -----       ---- ----
+  | S6 | S/R3 | S1 | --- | S4 | S/R5 | S5 | ____/ Cell 4.
+   ---- ------ ----       ---- ------ ----
+   | S8 | S5 | S3 |       | S6 | S7 | S8 |     ... etc ...
+    ---- ---- ----         ---- ---- ----
+       Cell 3.                Cell 5.
+.in 3
+
+.ce
+Figure 1:  SILC Network Topology
+
+
+A cell is formed when a server or servers connect to one router.  In
+SILC network normal server cannot directly connect to other normal
+server.  Normal server may only connect to SILC router which then
+routes the messages to the other servers in the cell.  Router servers
+on the other hand may connect to other routers to form the actual SILC
+network, as seen in above figure.  However, router is also able to act
+as normal SILC server; clients may connect to it the same way as to
+normal SILC server.  Normal server also cannot have active connections
+to more than one router.  Normal server cannot be connected to two
+different cells.  Router servers, on the other hand, may have as many
+router to router connections as needed.  Other direct routes between
+other routers is also possible in addition of the mandatory ring
+connections.  This leads into a hybrid ring-mesh network topology.
+
+There are many issues in this network topology that needs to be careful
+about.  Issues like routing, the size of the cells, the number of the
+routers in the SILC network and the capacity requirements of the
+routers.  These issues should be discussed in the Internet Community
+and additional documents on the issue may be written.
+
+
+.ti 0
+2.2 Communication Inside a Cell
+
+It is always guaranteed that inside a cell message is delivered to the
+recipient with at most two server hops.  A client which is connected to
+server in the cell and is talking on channel to other client connected
+to other server in the same cell, will have its messages delivered from
+its local server first to the router of the cell, and from the router
+to the other server in the cell.
+
+The following diagram represents this scenario:
+
+
+.in 25
+.nf
+1 --- S1     S4 --- 5
+         S/R
+ 2 -- S2     S3
+     /        |
+    4         3
+.in 3
+
+
+.ce
+Figure 2:  Communication Inside cell
+
+
+Example:  Client 1. connected to Server 1. send message to
+          Client 4. connected to Server 2. travels from Server 1.
+          first to Router which routes the message to Server 2.
+          which then sends it to the Client 4.  All the other
+          servers in the cell will not see the routed message.
+
+
+If the client is connected directly to the router, as router is also normal
+SILC server, the messages inside the cell are always delivered only with
+one server hop.  If clients communicating with each other are connected
+to the same server, no router interaction is needed.  This is the optimal
+situation of message delivery in the SILC network.
+
+
+.ti 0
+2.3 Communication in the Network
+
+If the message is destined to client that does not belong to local cell
+the message is routed to the router server to which the destination
+client belongs, if the local router is connected to destination router.
+If there is no direct connection to the destination router, the local
+router routes the message to its primary route.  The following diagram
+represents message sending between cells.
+
+
+
+.in 16
+.nf
+1 --- S1     S4 --- 5            S2 --- 1
+         S/R - - - - - - - - S/R
+ 2 -- S2     S3           S1
+     /        |             \\
+    4         3              2
+
+   Cell 1.               Cell 2.
+.in 3
+
+
+.ce
+Figure 3:  Communication Between Cells
+
+
+Example:  Client 5. connected to Server 4. in Cell 1. sends message
+          to Client 2. connected to Server 1. in Cell 2. travels
+          from Server 4. to Router which routes the message to
+          Router in Cell 2, which then routes the message to
+          Server 1.  All the other servers and routers in the
+          network will not see the routed message.
+
+
+The optimal case of message delivery from the client point of view is
+when clients are connected directly to the routers and the messages
+are delivered from one router to the other.
+
+
+.ti 0
+2.4 Channel Communication
+
+Messages may be sent to group of clients as well.  Sending messages to
+many clients works the same way as sending messages point to point, from
+message delivery point of view.  Security issues are another matter
+which are not discussed in this section.
+
+Router server handles the message routing to multiple recipients.  If
+any recipient is not in the same cell as the sender the messages are
+routed further.
+
+Server distributes the channel message to its local clients which are
+joined to the channel.  Router also distributes the message to its
+local clients on the channel.
+
+
+.ti 0
+2.5 Router Connections
+
+Router connections play very important role in making the SILC like
+network topology to work.  For example, sending broadcast packets in
+SILC network require special connections between routers; routers must
+be connected in a specific way.
+
+Every router has their primary route which is a connection to another
+router in the network.  Unless there is only two routers in the network
+must not routers use each other as their primary routes.  The router
+connections in the network must form a ring.
+
+Example with three routers in the network:
+
+
+.in 16
+.nf
+    S/R1 - < - < - < - < - < - < - S/R2
+     \\                               /
+      v                             ^
+       \\ - > -  > - S/R3 - > - > - /
+.in 3
+
+
+.ce
+Figure 4:  Router Connections
+
+
+Example:  Network with three routers.  Router 1. uses Router 2. as its
+          primary router.  Router 2. uses Router 3. as its primary router,
+          and Router 3. uses Router 1. as its primary router.  There may
+          be other direct connections between the routers but they must
+          not be used as primary routes.
+
+The above example is applicable to any amount of routers in the network
+except for two routers.  If there are only two routers in the network both
+routers must be able to handle situation where they use each other as their
+primary routes.
+
+The issue of router connections are very important especially with SILC
+broadcast packets.  Usually all router wide information in the network is
+distributed by SILC broadcast packets.  This sort of ring network, with
+ability to have other direct routes in the network can cause interesting
+routing problems.  The [SILC2] discusses the routing of packets in this
+sort of network in more detail.
+
+
+.ti 0
+3. SILC Specification
+
+This section describes the SILC protocol.  However, [SILC2] and
+[SILC3] describes other important protocols that are part of this SILC
+specification and must be read.
+
+
+.ti 0
+3.1 Client
+
+A client is a piece of software connecting to SILC server.  SILC client
+cannot be SILC server.  Purpose of clients is to provide the user
+interface of the SILC services for end user.  Clients are distinguished
+from other clients by unique Client ID.  Client ID is a 128 bit ID that
+is used in the communication in the SILC network.  The client ID is
+based on the user's IP address and nickname.  User use logical nicknames
+in communication which are then mapped to the corresponding Client ID.
+Client IDs are low level identifications and should not be seen by the
+end user.
+
+Clients provide other information about the end user as well. Information
+such as the nickname of the user, username and the host name of the end
+user and user's real name.  See section 3.2 Server for information of
+the requirements of keeping this information.
+
+The nickname selected by the user is not unique in the SILC network.
+There can be 2^8 same nicknames for one IP address.  As for comparison to
+IRC [IRC] where nicknames are unique this is a fundamental difference
+between SILC and IRC.  This typically causes the server names or client's
+host names to be used along with the nicknames on user interface to
+identify specific users when sending messages.  This feature of SILC
+makes IRC style nickname-wars obsolete as no one owns their nickname;
+there can always be someone else with the same nickname.  Also, any kind
+of nickname registering service becomes obsolete.  See the section 3.13.1
+for more information about nicknames.
+
+
+.ti 0
+3.1.1 Client ID
+
+Client ID is used to identify users in the SILC network.  The Client ID
+is unique to the extent that there can be 2^128 different Client IDs,
+and IDs based on IPv6 addresses extends this to 2^224 different Client
+IDs.  Collisions are not expected to happen.  The Client ID is defined
+as follows.
+
+.in 6
+128 bit Client ID based on IPv4 addresses:
+
+32 bit  Server ID IP address (bits 1-32)
+ 8 bit  Random number or counter
+88 bit  Truncated MD5 hash value of the nickname
+
+224 bit Client ID based on IPv6 addresses:
+
+128 bit  Server ID IP address (bits 1-128)
+  8 bit  Random number or counter
+ 88 bit  Truncated MD5 hash value of the nickname
+
+o Server ID IP address - Indicates the server where this
+  client is coming from.  The IP address hence equals the
+  server IP address where the client is connected.
+
+o Random number or counter - Random number to further
+  randomize the Client ID.  Another choice is to use
+  a counter starting from the zero (0).  This makes it
+  possible to have 2^8 same nicknames from the same
+  server IP address.
+
+o MD5 hash - MD5 hash value of the case folded nickname is
+  truncated taking 88 bits from the start of the hash value.
+  This hash value is used to search the user's Client ID
+  from the ID lists.  Note that the nickname MUST be prepared
+  using the stringprep [RFC3454] profile described in the
+  Appendix A before computing the MD5 hash.  See also the
+  section 3.13.1 for more information.
+
+.in 3
+Collisions could occur when more than 2^8 clients using same nickname
+from the same server IP address is connected to the SILC network.
+Server MUST be able to handle this situation by refusing to accept
+anymore of that nickname.
+
+Another possible collision may happen with the truncated hash value of
+the nickname.  It could be possible to have same truncated hash value
+for two different nicknames.  However, this is not expected to happen
+nor cause any serious problems if it would occur.  Nicknames are usually
+logical and it is unlikely to have two distinct logical nicknames
+produce same truncated hash value.
+
+
+.ti 0
+3.2 Server
+
+Servers are the most important parts of the SILC network.  They form the
+basis of the SILC, providing a point to which clients may connect to.
+There are two kinds of servers in SILC; normal servers and router servers.
+This section focus on the normal server and router server is described
+in the section 3.3 Router.
+
+Normal servers MUST NOT directly connect to other normal server.  Normal
+servers may only directly connect to router server.  If the message sent
+by the client is destined outside the local server it is always sent to
+the router server for further routing.  Server may only have one active
+connection to router on same port.  Normal server MUST NOT connect to other
+cell's router except in situations where its cell's router is unavailable.
+
+
+.ti 0
+3.2.1 Server's Local ID List
+
+Normal server keeps various information about the clients and their end
+users connected to it.  Every normal server MUST keep list of all locally
+connected clients, Client IDs, nicknames, usernames and host names and
+user's real name.  Normal servers only keeps local information and it
+does not keep any global information.  Hence, normal servers knows only
+about their locally connected clients.  This makes servers efficient as
+they do not have to worry about global clients.  Server is also responsible
+of creating the Client IDs for their clients.
+
+Normal server also keeps information about locally created channels and
+their Channel IDs.
+
+Hence, local list for normal server includes:
+
+.in 6
+server list        - Router connection
+   o Server name
+   o Server IP address
+   o Server ID
+   o Sending key
+   o Receiving key
+   o Public key
+
+client list        - All clients in server
+   o Nickname
+   o Username@host
+   o Real name
+   o Client ID
+   o Sending key
+   o Receiving key
+   o Public key
+
+channel list       - All channels in server
+   o Channel name
+   o Channel ID
+   o Client IDs on channel
+   o Client ID modes on channel
+   o Channel key
+.in 3
+
+
+.ti 0
+3.2.2 Server ID
+
+Servers are distinguished from other servers by unique 64 bit Server ID
+(for IPv4) or 160 bit Server ID (for IPv6).  The Server ID is used in
+the SILC to route messages to correct servers.  Server IDs also provide
+information for Client IDs, see section 3.1.1 Client ID.  Server ID is
+defined as follows.
+
+.in 6
+64 bit Server ID based on IPv4 addresses:
+
+32 bit  IP address of the server
+16 bit  Port
+16 bit  Random number
+
+160 bit Server ID based on IPv6 addresses:
+
+128 bit  IP address of the server
+ 16 bit  Port
+ 16 bit  Random number
+
+o IP address of the server - This is the real IP address of
+  the server.
+
+o Port - This is the port the server is bound to.
+
+o Random number - This is used to further randomize the Server ID.
+
+.in 3
+Collisions are not expected to happen in any conditions.  The Server ID
+is always created by the server itself and server is responsible of
+distributing it to the router.
+
+
+.ti 0
+3.2.3 SILC Server Ports
+
+The following ports has been assigned by IANA for the SILC protocol:
+
+.in 10
+silc            706/tcp    SILC
+silc            706/udp    SILC
+.in 3
+
+
+If there are needs to create new SILC networks in the future the port
+numbers must be officially assigned by the IANA.
+
+Server on network above privileged ports (>1023) SHOULD NOT be trusted
+as they could have been set up by untrusted party.
+
+
+.ti 0
+3.3 Router
+
+Router server in SILC network is responsible for keeping the cell together
+and routing messages to other servers and to other routers.  Router server
+is also a normal server thus clients may connect to it as it would be
+just normal SILC server.
+
+However, router servers has a lot of important tasks that normal servers
+do not have.  Router server knows everything and keeps the global state.
+They know all clients currently on SILC, all servers and routers and all
+channels in SILC.  Routers are the only servers in SILC that care about
+global information and keeping them up to date at all time.
+
+
+.ti 0
+3.3.1 Router's Local ID List
+
+Router server as well MUST keep local list of connected clients and
+locally created channels.  However, this list is extended to include all
+the informations of the entire cell, not just the server itself as for
+normal servers.
+
+However, on router this list is a lot smaller since routers do not need
+to keep information about user's nickname, username and host name and real
+name since these are not needed by the router.  The router keeps only
+information that it needs.
+
+Hence, local list for router includes:
+
+.in 6
+server list        - All servers in the cell
+   o Server name
+   o Server ID
+   o Router's Server ID
+   o Sending key
+   o Receiving key
+
+client list        - All clients in the cell
+   o Client ID
+
+channel list       - All channels in the cell
+   o Channel ID
+   o Client IDs on channel
+   o Client ID modes on channel
+   o Channel key
+.in 3
+
+
+Note that locally connected clients and other information include all the
+same information as defined in section section 3.2.1 Server's Local ID
+List.  Router MAY also cache same detailed information for other clients
+if needed.
+
+
+.ti 0
+3.3.2 Router's Global ID List
+
+Router server MUST also keep global list.  Normal servers do not have
+global list as they know only about local information.  Global list
+includes all the clients on SILC, their Client IDs, all created channels
+and their Channel IDs and all servers and routers on SILC and their
+Server IDs.  That is said, global list is for global information and the
+list must not include the local information already on the router's local
+list.
+
+Note that the global list does not include information like nicknames,
+usernames and host names or user's real names.  Router does not need to
+keep these informations as they are not needed by the router.  This
+information is available from the client's server which maybe queried
+when needed.
+
+Hence, global list includes:
+
+.in 6
+server list        - All servers in SILC
+   o Server name
+   o Server ID
+   o Router's Server ID
+
+client list        - All clients in SILC
+   o Client ID
+
+channel list       - All channels in SILC
+   o Channel ID
+   o Client IDs on channel
+   o Client ID modes on channel
+.in 3
+
+
+
+.ti 0
+3.3.3 Router's Server ID
+
+Router's Server ID is equivalent to normal Server ID.  As routers are
+normal servers same types of IDs applies for routers as well.  See
+section 3.2.2 Server ID.
+
+
+
+
+.ti 0
+3.4 Channels
+
+A channel is a named group of one or more clients which will all receive
+messages addressed to that channel.  The channel is created when first
+client requests JOIN command to the channel, and the channel ceases to
+exist when the last client has left it.  When channel exists, any client
+can reference it using the Channel ID of the channel.  If the channel has
+a founder mode set and last client leaves the channel the channel does
+not cease to exist.  The founder mode can be used to make permanent
+channels in the network.  The founder of the channel can regain the
+channel founder privileges on the channel later when he joins the
+channel.
+
+Channel names are unique although the real uniqueness comes from 64 bit
+Channel ID.  However, channel names are still unique and no two global
+channels with same name may exist.  See the section 3.13.1 for more
+information about channel names.
+
+Channels can have operators that can administrate the channel and operate
+all of its modes.  The following operators on channel exist on the
+SILC network.
+
+.in 6
+o Channel founder - When channel is created the joining client becomes
+  channel founder.  Channel founder is channel operator with some more
+  privileges.  Basically, channel founder can fully operate the channel
+  and all of its modes.  The privileges are limited only to the
+  particular channel.  There can be only one channel founder per
+  channel.  Channel founder supersedes channel operator's privileges.
+
+  Channel founder privileges cannot be removed by any other operator on
+  channel.  When channel founder leaves the channel there is no channel
+  founder on the channel.  However, it is possible to set a mode for
+  the channel which allows the original channel founder to regain the
+  founder privileges even after leaving the channel.  Channel founder
+  also cannot be removed by force from the channel.
+
+o Channel operator - When client joins to channel that has not existed
+  previously it will become automatically channel operator (and channel
+  founder discussed above).  Channel operator is able to administrate the
+  channel, set some modes on channel, remove a badly behaving client
+  from the channel and promote other clients to become channel
+  operator.  The privileges are limited only to the particular channel.
+
+  Normal channel user may be promoted (opped) to channel operator
+  gaining channel operator privileges.  Channel founder or other
+  channel operator may also demote (deop) channel operator to normal
+  channel user.
+.in 3
+
+
+
+
+.ti 0
+3.4.1 Channel ID
+
+Channels are distinguished from other channels by unique Channel ID.
+The Channel ID is a 64 bit ID (for IPv4) or 160 bit ID (for IPv6), and
+collisions are not expected to happen in any conditions.  Channel names
+are just for logical use of channels.  The Channel ID is created by the
+server where the channel is created.  The Channel ID is defined as
+follows.
+
+.in 6
+64 bit Channel ID based on IPv4 addresses:
+
+32 bit  Router's Server ID IP address (bits 1-32)
+16 bit  Router's Server ID port (bits 33-48)
+16 bit  Random number or counter
+
+160 bit Channel ID based on IPv6 addresses:
+
+128 bit  Router's Server ID IP address (bits 1-128)
+ 16 bit  Router's Server ID port (bits 129-144)
+ 16 bit  Random number or counter
+
+o Router's Server ID IP address - Indicates the IP address of
+  the router of the cell where this channel is created.  This is
+  taken from the router's Server ID.  This way SILC router knows
+  where this channel resides in the SILC network.
+
+o Router's Server ID port - Indicates the port of the channel on
+  the server.  This is taken from the router's Server ID.
+
+o Random number or counter - To further randomize the Channel ID.
+  Another choice is to use a counter starting from zero (0).
+  This makes sure that there are no collisions.  This also means
+  that in a cell there can be 2^16 different channels.
+.in 3
+
+
+.ti 0
+3.5 Operators
+
+Operators are normal users with extra privileges to their server or
+router.  Usually these people are SILC server and router administrators
+that take care of their own server and clients on them.  The purpose of
+operators is to administrate the SILC server or router.  However, even
+an operator with highest privileges is not able to enter invite-only
+channels, to gain access to the contents of encrypted and authenticated
+packets traveling in the SILC network or to gain channel operator
+privileges on public channels without being promoted.  They have the
+same privileges as any normal user except they are able to administrate
+their server or router.
+
+
+.ti 0
+3.6 SILC Commands
+
+Commands are very important part on SILC network especially for client
+which uses commands to operate on the SILC network.  Commands are used
+to set nickname, join to channel, change modes and many other things.
+
+Client usually sends the commands and server replies by sending a reply
+packet to the command.  Server MAY also send commands usually to serve
+the original client's request.  Usually server cannot send commands to
+clients, however there MAY be commands that allow the server to send
+commands to client.  By default servers MAY send commands only to other
+servers and routers.
+
+Note that the command reply is usually sent only after client has sent
+the command request but server is allowed to send command reply packet
+to client even if client has not requested the command.  Client MAY
+choose to ignore the command reply.
+
+It is expected that some of the commands may be misused by clients
+resulting various problems on the server side.  Every implementation
+SHOULD assure that commands may not be executed more than once, say,
+in two (2) seconds.  However, to keep response rate up, allowing for
+example five (5) commands before limiting is allowed.  It is RECOMMENDED
+that commands such as SILC_COMMAND_NICK, SILC_COMMAND_JOIN,
+SILC_COMMAND_LEAVE and SILC_COMMAND_KILL SHOULD be limited in all cases
+as they require heavy operations.  This should be sufficient to prevent
+the misuse of commands.
+
+SILC commands are described in [SILC4].
+
+
+.ti 0
+3.7 SILC Packets
+
+Packets are naturally the most important part of the protocol and the
+packets are what actually makes the protocol.  Packets in SILC network
+are always encrypted using, usually the shared secret session key
+or some other key, for example, channel key, when encrypting channel
+messages.  It is not possible to send a packet in SILC network without
+encryption.  The SILC Packet Protocol is a wide protocol and is described
+in [SILC2].  This document does not define or describe details of
+SILC packets.
+
+
+.ti 0
+3.8 Packet Encryption
+
+All packets passed in SILC network MUST be encrypted.  This section
+gives generic description of how packets must be encrypted in the SILC
+network.  The detailed description of the actual encryption process
+of the packets are described in [SILC2].
+
+Client and its server shares secret symmetric session key which is
+established by the SILC Key Exchange Protocol, described in [SILC3].
+Every packet sent from client to server, with exception of packets for
+channels, are encrypted with this session key.
+
+Channels have a channel key that are shared by every client on the channel.
+However, the channel keys are cell specific thus one cell does not know
+the channel key of the other cell, even if that key is for same channel.
+Channel key is also known by the routers and all servers that have clients
+on the channel.  However, channels MAY have channel private keys that are
+entirely local setting for the client.  All clients on the channel MUST
+know the channel private key beforehand to be able to talk on the
+channel.  In this case, no server or router knows the key for the channel.
+
+Server shares secret symmetric session key with router which is
+established by the SILC Key Exchange Protocol.  Every packet passed from
+server to router, with exception of packets for channels, are encrypted
+with the shared session key.  Same way, router server shares secret
+symmetric key with its primary router.  However, every packet passed
+from router to other router, including packets for channels, are
+encrypted with the shared session key.  Every router connection MUST
+have their own session keys.
+
+
+.ti 0
+3.8.1 Determination of the Source and the Destination
+
+The source and the destination of the packet needs to be determined
+to be able to route the packets to correct receiver.  This information
+is available in the SILC Packet Header which is included in all packets
+sent in SILC network.  The SILC Packet Header is described in [SILC2].
+
+The header MUST be encrypted with the session key of whom is the next
+receiver of the packet along the route.  The receiver of the packet, for
+example a router along the route, is able to determine the sender and the
+destination of the packet by decrypting the SILC Packet Header and
+checking the IDs attached to the header.  The IDs in the header will
+tell to where the packet needs to be sent and where it is coming from.
+
+The header in the packet MUST NOT change during the routing of the
+packet.  The original sender, for example client, assembles the packet
+and the packet header and server or router between the sender and the
+receiver MUST NOT change the packet header.  Note however, that some
+packets such as commands may be resent by a server to serve the client's
+original command.  In this case the command packet sent by the server
+includes the server's IDs as it is a different packet.  When server
+or router receives a packet it MUST verify that the Source ID is
+valid and correct ID for that sender.
+
+Note that the packet and the packet header may be encrypted with
+different keys.  For example, packets to channels are encrypted with
+the channel key, however, the header is encrypted with the session key
+as described above.  However, the header and the packet may be encrypted
+with same key.  This is the case, for example, with command packets.
+
+
+.ti 0
+3.8.2 Client To Client
+
+The process of message delivery and encryption from client to another
+client is as follows.
+
+Example:  Private message from client to another client on different
+          servers.  Clients do not share private message delivery
+          keys; normal session keys are used.
+
+o Client 1 sends encrypted packet to its server.  The packet is
+  encrypted with the session key shared between client and its
+  server.
+
+o Server determines the destination of the packet and decrypts
+  the packet.  Server encrypts the packet with session key shared
+  between the server and its router, and sends the packet to the
+  router.
+
+o Router determines the destination of the packet and decrypts
+  the packet.  Router encrypts the packet with session key
+  shared between the router and the destination server, and sends
+  the packet to the server.
+
+o Server determines the client to which the packet is destined
+  to and decrypts the packet.  Server encrypts the packet with
+  session key shared between the server and the destination client,
+  and sends the packet to the client.
+
+o Client 2 decrypts the packet.
+
+
+Example:  Private message from client to another client on different
+          servers.  Clients have established a secret shared private
+          message delivery key with each other and that is used in
+          the message encryption.
+
+o Client 1 sends encrypted packet to its server.  The packet header
+  is encrypted with the session key shared between the client and
+  server, and the private message is encrypted with the private
+  message delivery key shared between clients.
+
+o Server determines the destination of the packet and sends the
+  packet to the router.  Header is encrypted with the session key.
+
+o Router determines the destination of the packet and sends the
+  packet to the server.  Header is encrypted with the session key.
+
+o Server determines the client to which the packet is destined
+  to and sends the packet to the client.  Header is encrypted with
+  the session key.
+
+o Client 2 decrypts the packet with the secret shared key.
+
+If clients share secret key with each other the private message
+delivery is much simpler since servers and routers between the
+clients do not need to decrypt and re-encrypt the entire packet.
+The packet header however is always encrypted with session key and
+is decrypted and re-encrypted with the session key of next recipient.
+
+The process for clients on same server is much simpler as there is
+no need to send the packet to the router.  The process for clients
+on different cells is same as above except that the packet is routed
+outside the cell.  The router of the destination cell routes the
+packet to the destination same way as described above.
+
+
+.ti 0
+3.8.3 Client To Channel
+
+Process of message delivery from client on channel to all the clients
+on the channel.
+
+Example:  Channel of four users; two on same server, other two on
+          different cells.  Client sends message to the channel.
+          Packet header is encrypted with the session key, message
+          data is encrypted with channel key.
+
+o Client 1 encrypts the packet with channel key and sends the
+  packet to its server.
+
+o Server determines local clients on the channel and sends the
+  packet to the Client on the same server.  Server then sends
+  the packet to its router for further routing.
+
+o Router determines local clients on the channel, if found
+  sends packet to the local clients.  Router determines global
+  clients on the channel and sends the packet to its primary
+  router or fastest route.
+
+o (Other router(s) do the same thing and sends the packet to
+   the server(s).)
+
+o Server determines local clients on the channel and sends the
+  packet to the client.
+
+o All clients receiving the packet decrypts it.
+
+
+.ti 0
+3.8.4 Server To Server
+
+Server to server packet delivery and encryption is described in above
+examples. Router to router packet delivery is analogous to server to
+server.  However, some packets, such as channel packets, are processed
+differently.  These cases are described later in this document and
+more in detail in [SILC2].
+
+
+.ti 0
+3.9 Key Exchange And Authentication
+
+Key exchange is done always when for example client connects to server
+but also when server and router, and router and another router connect
+to each other.  The purpose of key exchange protocol is to provide secure
+key material to be used in the communication.  The key material is used
+to derive various security parameters used to secure SILC packets.  The
+SILC Key Exchange protocol is described in detail in [SILC3].
+
+Authentication is done after key exchange protocol has been successfully
+completed.  The purpose of authentication is to authenticate for example
+client connecting to the server.  However, clients MAY be accepted
+to connect to server without explicit authentication.  Servers are
+REQUIRED to use authentication protocol when connecting.  The
+authentication may be based on passphrase (pre-shared secret) or public
+key based on digital signatures.  All passphrases sent in SILC protocol
+MUST be UTF-8 [RFC3629] encoded. The connection authentication protocol
+is described in detail in [SILC3].
+
+
+.ti 0
+3.9.1 Authentication Payload
+
+Authentication Payload is used separately from the SKE and the Connection
+Authentication protocols.  It can be used during the session to
+authenticate with a remote.  For example, a client can authenticate
+itself to a server to become server operator.  In this case,
+Authentication Payload is used.
+
+The format of the Authentication Payload is as follows:
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|        Payload Length         |     Authentication Method     |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|      Public Data Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Public Data                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|   Authentication Data Length  |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                       Authentication Data                     ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 5:  Authentication Payload
+
+
+.in 6
+o Payload Length (2 bytes) - Length of the entire payload.
+
+o Authentication Method (2 bytes) - The method of the
+  authentication.  The authentication methods are defined
+  in [SILC2] in the Connection Auth Request Payload.  The NONE
+  authentication method SHOULD NOT be used.
+
+o Public Data Length (2 bytes) - Indicates the length of
+  the Public Data field.
+
+o Public Data (variable length) - This is defined only if
+  the authentication method is public key.  If it is any other
+  this field MAY include random data for padding purposes.
+  However, in this case the field MUST be ignored by the
+  receiver.
+
+  When the authentication method is public key this includes
+  128 to 4096 bytes of non-zero random data that is used in
+  the signature process, described subsequently.
+
+o Authentication Data Length (2 bytes) - Indicates the
+  length of the Authentication Data field.  If zero (0)
+  value is found in this field the payload MUST be
+  discarded.
+
+o Authentication Data (variable length) - Authentication
+  method dependent authentication data.
+.in 3
+
+
+If the authentication method is passphrase-based, the Authentication
+Data field includes the plaintext UTF-8 encoded passphrase.  It is safe
+to send plaintext passphrase since the entire payload is encrypted.  In
+this case the Public Data Length is set to zero (0), but MAY also include
+random data for padding purposes.  It is also RECOMMENDED that maximum
+amount of padding is applied to SILC packet when using passphrase-based
+authentication.  This way it is not possible to approximate the length
+of the passphrase from the encrypted packet.
+
+If the authentication method is public key based (or certificate)
+the Authentication Data is computed as follows:
+
+  HASH = hash(random bytes | ID | public key (or certificate));
+  Authentication Data = sign(HASH);
+
+The hash() and the sign() are the hash function and the public key
+cryptography function selected in the SKE protocol, unless otherwise
+stated in the context where this payload is used.  The public key
+is SILC style public key unless certificates are used.  The ID is the
+entity's ID (Client or Server ID) which is authenticating itself.  The
+ID encoding is described in [SILC2].  The random bytes are non-zero
+random bytes of length between 128 and 4096 bytes, and will be included
+into the Public Data field as is.
+
+The receiver will compute the signature using the random data received
+in the payload, the ID associated to the connection and the public key
+(or certificate) received in the SKE protocol.  After computing the
+receiver MUST verify the signature.  Also in case of public key
+authentication this payload is encrypted.
+
+
+.ti 0
+3.10 Algorithms
+
+This section defines all the allowed algorithms that can be used in
+the SILC protocol.  This includes mandatory cipher, mandatory public
+key algorithm and MAC algorithms.
+
+
+.ti 0
+3.10.1 Ciphers
+
+Cipher is the encryption algorithm that is used to protect the data
+in the SILC packets.  See [SILC2] for the actual encryption process and
+definition of how it must be done.  SILC has a mandatory algorithm that
+must be supported in order to be compliant with this protocol.
+
+The following ciphers are defined in SILC protocol:
+
+aes-256-cbc          AES in CBC mode, 256 bit key            (REQUIRED)
+aes-256-ctr          AES in CTR mode, 256 bit key            (RECOMMENDED)
+aes-256-rcbc         AES in randomized CBC mode, 256 bit key (OPTIONAL)
+aes-192-<mode>       AES in <mode> mode, 192 bit key         (OPTIONAL)
+aes-128-<mode>       AES in <mode> mode, 128 bit key         (RECOMMENDED)
+twofish-256-<mode>   Twofish in <mode> mode, 256 bit key     (OPTIONAL)
+twofish-192-<mode>   Twofish in <mode> mode, 192 bit key     (OPTIONAL)
+twofish-128-<mode>   Twofish in <mode> mode, 128 bit key     (OPTIONAL)
+cast-256-<mode>      CAST-256 in <mode> mode, 256 bit key    (OPTIONAL)
+cast-192-<mode>      CAST-256 in <mode> mode, 192 bit key    (OPTIONAL)
+cast-128-<mode>      CAST-256 in <mode> mode, 128 bit key    (OPTIONAL)
+serpent-<len>-<mode> Serpent in <mode> mode, <len> bit key   (OPTIONAL)
+rc6-<len>-<mode>     RC6 in <mode> mode, <len> bit key       (OPTIONAL)
+mars-<len>-<mode>    MARS in <mode> mode, <len> bit key      (OPTIONAL)
+none                 No encryption                           (OPTIONAL)
+
+The <mode> is either "cbc", "ctr" or "rcbc".  Other encryption modes MAY
+be defined to be used in SILC using the same name format.  The <len> is
+either 256, 192 or 128 bit key length.  Also, additional ciphers MAY be
+defined to be used in SILC by using the same name format as above.
+
+Algorithm "none" does not perform any encryption process at all and
+thus is not recommended to be used.  It is recommended that no client
+or server implementation would accept none algorithm except in special
+debugging mode.
+
+
+.ti 0
+3.10.1.1 CBC Mode
+
+The "cbc" encryption mode is CBC mode with inter-packet chaining.  This
+means that the Initialization Vector (IV) for the next encryption block
+is the previous ciphertext block.  The very first IV MUST be random and
+is generated as described in [SILC3].
+
+
+.ti 0
+3.10.1.2 CTR Mode
+
+The "ctr" encryption mode is Counter Mode (CTR).  The CTR mode in SILC is
+stateful in encryption and decryption.  Both sender and receiver maintain
+the counter for the CTR mode and thus can precompute the key stream for
+encryption and decryption.  By default, CTR mode does not require
+plaintext padding, however implementations MAY apply padding to the
+packets.  If the last key block is larger than the last plaintext block
+the resulted value is truncated to the size of the plaintext block and
+the most significant bits are used.  When sending authentication data
+inside packets the maximum amount of padding SHOULD be applied with
+CTR mode as well.
+
+In CTR mode only the encryption operation of the cipher is used.  The
+decryption operation is not needed since both encryption and decryption
+process is simple XOR with the plaintext block and the key stream block.
+
+The counter block is used to create the key for the CTR mode.  When
+SILC specifications refer to Initialization Vector (IV) in general cases,
+in case of CTR mode it refers to the counter block.  The format of the
+128 bit counter block is as follows:
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                   Truncated HASH from SKE                     |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                Sending/Receiving IV from SKE                  |
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                        Block Counter                          |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 6:  Counter Block
+
+.in 6
+o Truncated HASH from SKE (4 bytes) - This value is the first 4
+  bytes from the HASH value that was computed as a result of SKE
+  protocol.  This acts as session identifier and each rekey MUST
+  produce a new HASH value.
+
+o Sending/Receiving IV from SKE (8 bytes) - This value is the
+  first 8 bytes from the Sending IV or Receiving IV generated in
+  the SKE protocol.  When this mode is used to encrypt sending
+  traffic the Sending IV is used, when used to decrypt receiving
+  traffic the Receiving IV is used.  This assures that two parties
+  of the protocol use different IV for sending traffic.  Each rekey
+  MUST produce a new value.
+
+o Block Counter (4 bytes) - This is the counter value for the
+  counter block and is MSB ordered number starting from one (1)
+  value for first block and incrementing for subsequent blocks.
+  The same value MUST NOT be used twice.  The rekey MUST be
+  performed before this counter value wraps.
+.in 3
+
+CTR mode MUST NOT be used with "none" MAC.  Implementations also MUST
+assure that the same counter block is not used to encrypt more than
+one block.  Also, the key material used with CTR mode MUST be fresh
+key material.  Static keys (pre-shared keys) MUST NOT be used with
+CTR mode.  For this reason using CTR mode to encrypt for example
+channel messages or private messages with a pre-shared key is
+inappropriate.  For private messages, the Key Agreement could be
+performed to produce fresh key material.
+
+If the IV Included flag was negotiated in SKE, or CTR mode is used to
+protect channel messages where the counter block will be included in the
+Message Payload, implementations SHOULD still use the same counter block
+format as defined above.  However, implementations are RECOMMENDED to
+replace the Truncated HASH field with a 32 bit random value for each IV
+(counter block) per encrypted SILC packet.  Also note, that in this case
+the decryption process is not stateful and receiver cannot precompute the
+key stream.
+
+
+.ti 0
+3.10.1.3 Randomized CBC Mode
+
+The "rcbc" encryption mode is CBC mode with randomized IV.  This means
+that each IV for each packet MUST be chosen randomly.  When encrypting
+more than one block the normal inter-packet chaining is used, but for
+the first block new random IV is selected in each packet.  In this mode
+the IV is appended at the end of the last ciphertext block and thus
+delivered to the recipient.  This mode increases the ciphertext size by
+one ciphertext block.  Note also that some data payloads in SILC are
+capable of delivering the IV to the recipient.  When explicitly
+encrypting these payloads with randomized CBC the IV MUST NOT be appended
+at the end of the ciphertext, but is placed at the specified location
+in the payload.  However, Message Payload for example has the IV at
+the location which is equivalent to placing it after the last ciphertext
+block.  When using CBC mode with such payloads it is actually equivalent
+to using randomized CBC since the IV is selected in random and included
+in the ciphertext.
+
+
+.ti 0
+3.10.2 Public Key Algorithms
+
+Public keys are used in SILC to authenticate entities in SILC network
+and to perform other tasks related to public key cryptography.  The
+public keys are also used in the SILC Key Exchange protocol [SILC3].
+
+The following public key algorithms are defined in SILC protocol:
+
+.in 6
+rsa        RSA  (REQUIRED)
+dss        DSS  (OPTIONAL)
+.in 3
+
+DSS is described in [Menezes].  The RSA MUST be implemented according
+PKCS #1 [PKCS1].  The mandatory PKCS #1 implementation in SILC MUST be
+compliant to either PKCS #1 version 1.5 or newer with the following
+notes: The signature encoding is always in same format as the encryption
+encoding regardless of the PKCS #1 version.  The signature with appendix
+(with hash algorithm OID in the data) MUST NOT be used in the SILC.  The
+rationale for this is that there is no binding between the PKCS #1 OIDs
+and the hash algorithms used in the SILC protocol.  Hence, the encoding
+is always in PKCS #1 version 1.5 format.
+
+Additional public key algorithms MAY be defined to be used in SILC.
+
+When signatures are computed in SILC the computing of the signature is
+represented as sign().  The signature computing procedure is dependent
+of the public key algorithm, and the public key or certificate encoding.
+When using SILC public key the signature is computed as described in
+previous paragraph for RSA and DSS keys.  If the hash function is not
+specified separately for signing process SHA-1 MUST be used.  When using
+SSH2 public keys the signature is computed as described in [SSH-TRANS].
+When using X.509 version 3 certificates the signature is computed as
+described in [PKCS7].  When using OpenPGP certificates the signature is
+computed as described in [PGP].
+
+
+.ti 0
+3.10.2.1 Multi-Precision Integers
+
+Multi-Precision (MP) integers in SILC are encoded and decoded as defined
+in PKCS #1 [PKCS1].  MP integers are unsigned, encoded with desired octet
+length.  This means that if the octet length is more than the actual
+length of the integer one or more leading zero octets will appear at the
+start of the encoding.  The actual length of the integer is the bit size
+of the integer not counting any leading zero bits.
+
+
+.ti 0
+3.10.3 Hash Functions
+
+Hash functions are used as part of MAC algorithms defined in the next
+section.  They are also used in the SILC Key Exchange protocol defined
+in the [SILC3].
+
+The following Hash algorithm are defined in SILC protocol:
+
+.in 6
+sha1             SHA-1, length = 20      (REQUIRED)
+md5              MD5, length = 16        (RECOMMENDED)
+.in 3
+
+
+.ti 0
+3.10.4 MAC Algorithms
+
+Data integrity is protected by computing a message authentication code
+(MAC) of the packet data.  See [SILC2] for details how to compute the
+MAC for a packet.
+
+The following MAC algorithms are defined in SILC protocol:
+
+.in 6
+hmac-sha1-96     HMAC-SHA1, length = 12 bytes  (REQUIRED)
+hmac-md5-96      HMAC-MD5, length = 12 bytes   (OPTIONAL)
+hmac-sha1        HMAC-SHA1, length = 20 bytes  (OPTIONAL)
+hmac-md5         HMAC-MD5, length = 16 bytes   (OPTIONAL)
+none             No MAC                        (OPTIONAL)
+.in 3
+
+The "none" MAC is not recommended to be used as the packet is not
+authenticated when MAC is not computed.  It is recommended that no
+client or server would accept none MAC except in special debugging
+mode.
+
+The HMAC algorithm is described in [HMAC].  The hash algorithms used
+in HMACs, the SHA-1 is described in [RFC3174] and MD5 is described
+in [RFC1321].
+
+Additional MAC algorithms MAY be defined to be used in SILC.
+
+
+.ti 0
+3.10.5 Compression Algorithms
+
+SILC protocol supports compression that may be applied to unencrypted
+data.  It is recommended to use compression on slow links as it may
+significantly speed up the data transmission.  By default, SILC does not
+use compression which is the mode that must be supported by all SILC
+implementations.
+
+The following compression algorithms are defined:
+
+.in 6
+none        No compression               (REQUIRED)
+zlib        GNU ZLIB (LZ77) compression  (OPTIONAL)
+.in 3
+
+Additional compression algorithms MAY be defined to be used in SILC.
+
+
+.ti 0
+3.11 SILC Public Key
+
+This section defines the type and format of the SILC public key.  All
+implementations MUST support this public key type.  See [SILC3] for
+other optional public key and certificate types allowed in the SILC
+protocol.  Public keys in SILC may be used to authenticate entities
+and to perform other tasks related to public key cryptography.
+
+The format of the SILC Public Key is as follows:
+
+
+
+
+
+
+
+
+.in 5
+.nf
+                     1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                        Public Key Length                      |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|     Algorithm Name Length     |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                         Algorithm Name                        ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|       Identifier Length       |                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+|                                                               |
+~                           Identifier                          ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                                                               |
+~                           Public Data                         ~
+|                                                               |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+.in 3
+
+.ce
+Figure 5:  SILC Public Key
+
+
+.in 6
+o Public Key Length (4 bytes) - Indicates the full length
+  of the SILC Public Key, not including this field.
+
+o Algorithm Name Length (2 bytes) - Indicates the length
+  of the Algorithm Length field, not including this field.
+
+o Algorithm name (variable length) - Indicates the name
+  of the public key algorithm that the key is.  See the
+  section 3.10.2 Public Key Algorithms for defined names.
+
+o Identifier Length (2 bytes) - Indicates the length of
+  the Identifier field, not including this field.
+
+o Identifier (variable length) - Indicates the identifier
+  of the public key.  This data can be used to identify
+  the owner of the key.  The identifier is of the following
+  format:
+
+     UN   User name
+     HN   Host name or IP address
+     RN   Real name
+     E    EMail address
+     O    Organization
+     C    Country
+
+
+  Examples of an identifier:
+
+    `UN=priikone, HN=poseidon.pspt.fi, E=priikone@poseidon.pspt.fi'
+
+    `UN=sam, HN=dummy.fi, RN=Sammy Sam, O=Company XYZ, C=Finland'
+
+  At least user name (UN) and host name (HN) MUST be provided as
+  identifier.  The fields are separated by commas (`,').  If
+  comma is in the identifier string it must be escaped as `\\,',
+  for example, `O=Company XYZ\\, Inc.'.  Other characters that
+  require escaping are listed in [RFC2253] and are to be escaped
+  as defined therein.
+
+o Public Data (variable length) - Includes the actual
+  public data of the public key.
+
+  The format of this field for RSA algorithm is
+  as follows:
+
+     4 bytes            Length of e
+     variable length    e
+     4 bytes            Length of n
+     variable length    n
+
+
+  The format of this field for DSS algorithm is
+  as follows:
+
+     4 bytes            Length of p
+     variable length    p
+     4 bytes            Length of q
+     variable length    q
+     4 bytes            Length of g
+     variable length    g
+     4 bytes            Length of y
+     variable length    y
+
+  The variable length fields are multiple precession
+  integers encoded as strings in both examples.
+
+  Other algorithms must define their own type of this
+  field if they are used.
+.in 3
+
+All fields in the public key are in MSB (most significant byte first)
+order.  All strings in the public key MUST be UTF-8 encoded.
+
+If an external protocol needs to refer to SILC Public Key by name, the
+names "silc-rsa" and "silc-dss" for SILC Public Key based on RSA algorithm
+and SILC Public Key based on DSS algorithm, respectively, are to be used.
+However, this SILC specification does not use these names directly, and
+they are defined here for external protocols (protocols that may like
+to use SILC Public Key).
+
+
+.ti 0
+3.12 SILC Version Detection
+
+The version detection of both client and server is performed at the
+connection phase while executing the SILC Key Exchange protocol.  The
+version identifier is exchanged between initiator and responder.  The
+version identifier is of the following format:
+
+.in 6
+SILC-<protocol version>-<software version>
+.in 3
+
+The version strings are of the following format:
+
+.in 6
+protocol version = <major>.<minor>
+software version = <major>[.<minor>[.<build or vendor string>]]
+.in 3
+
+Protocol version MUST provide both major and minor version.  Currently
+implementations MUST set the protocol version and accept at least the
+protocol version as SILC-1.2-<software version>.  If new protocol version
+causes incompatibilities with older version the <minor> version number
+MUST be incremented.  The <major> is incremented if new protocol version
+is fully incompatible.
+
+Software version MAY provide major, minor and build (vendor) version.
+The software version MAY be freely set and accepted.  The version string
+MUST consist of printable US-ASCII characters.
+
+Thus, the version strings could be, for example:
+
+.in 6
+SILC-1.1-2.0.2
+SILC-1.0-1.2
+SILC-1.2-1.0.VendorXYZ
+SILC-1.2-2.4.5 Vendor Limited
+.in 3
+
+
+.ti 0
+3.13 UTF-8 Strings in SILC
+
+By default all strings that are sent in SILC protocol MUST be UTF-8
+[RFC3269] encoded, unless otherwise defined.  This means that any string
+sent inside for example, command, command reply, notify or any packet
+payload is UTF-8 encoded.  Also nicknames, channel names, server names,
+and hostnames are UTF-8 encoded.  This definition does not affect
+messages sent in SILC, as the Message Payload provides its own mechanism
+to indicate whether a message is UTF-8 text message, data message, which
+may use its own character encoding, or pure binary message [SILC2].
+
+Certain limitations are imposed on the UTF-8 encoded strings in SILC.
+The UTF-8 encoded strings MUST NOT include any characters that are
+marked in the Unicode standard as control codes, noncharacters,
+reserved or private range characters, or any other illegal Unicode
+characters.  Also the BOM (Byte-Order Mark) MUST NOT be used as byte
+order signature in UTF-8 encoded strings.  A string containing these
+characters MUST be treated as malformed UTF-8 encoding.
+
+The Unicode standard defines that malformed sequences shall be signalled
+by replacing the sequence with a replacement character.  Even though,
+in case of SILC these strings may not be malformed UTF-8 encodings
+they MUST be treated as malformed strings.  Implementation MAY use
+a replacement character, however, the character Unicode standard defines
+MUST NOT be used, but another character must be chosen.  It is, however,
+RECOMMENDED that an error is returned instead of using replacement
+character if it is possible.  For example, when setting a nickname
+with SILC_COMMAND_NICK command, implementation is able to send error
+indication back to the command sender.  It must be noted that on server
+implementation if a character sequence is merely outside of current
+character subset, but is otherwise valid character, it MUST NOT be
+replaced by a replacement character.
+
+On user interface where UTF-8 strings are displayed the implementation
+is RECOMMENDED to escape any character that it is unable to render
+properly.  The escaping may be done for example as described in
+[RFC2253].  The escaping makes it possible to retrieve the original
+UTF-8 encoding.  Alternatively, a replacement character may be used
+if it does not cause practical problems to the implementation.
+
+
+.ti 0
+3.13.1 UTF-8 Identifier Strings
+
+Identifier strings are special strings in SILC protocol that require
+more careful processing, than the general UTF-8 strings described in the
+previous section.  These strings include the nicknames, server names, 
+hostnames and some other identifier strings.  These strings are prepared 
+using the stringprep [RFC3454] standard.  The Appendix A defines the 
+stringprep profile for SILC identifier strings and conforming 
+implementation MUST use the profile to prepare any identifier string.
+
+The stringprep profile describes how identifier strings are prepared,
+what characters they may include, and which characters are prohibited.
+Identifier strings with prohibited characters MUST be treated as
+malformed strings.
+
+The channel name is also special identifier strings with some slight
+differences to other identifier strings.  The Appendix B defines the
+stringprep profile for the channel name strings and conforming
+implementation MUST use the profile to prepare any channel name string.
+
+Because of the profile the identifier strings in SILC may generally
+include only letters, numbers, most punctuation characters, and some
+other characters.  For practical reasons most symbol characters and
+many other special characters are prohibited.  All identifier strings
+are case folded and comparing the identifier strings MUST be done as
+caseless matching.
+
+In general, the identifier strings does not have a maximum length.
+However, the length of a nickname string MUST NOT exceed 128 bytes, and
+the length of a channel name string MUST NOT exceed 256 bytes.  Since
+these strings are UTF-8 encoded the length of one character may be
+longer than one byte.  This means that the character length of these
+strings may be shorter than the maximum length of the string in bytes.
+The minimum length of an identifier string MUST be at least one character,
+which may be one byte or more in length.  Implementation MAY limit the
+maximum length of an identifier string, with exception of the nickname
+and channel name strings which has the explicit length definition.
+
+
+.ti 0
+3.14 Backup Routers
+
+Backup routers may exist in the cell in addition to the primary router.
+However, they must not be active routers or act as routers in the cell.
+Only one router may be acting as primary router in the cell.  In the case
+of failure of the primary router one of the backup routers becomes active.
+The purpose of backup routers are in case of failure of the primary router
+to maintain working connections inside the cell and outside the cell and
+to avoid netsplits.
+
+Backup routers are normal servers in the cell that are prepared to take
+over the tasks of the primary router if needed.  They need to have at
+least one direct and active connection to the primary router of the cell.
+This communication channel is used to send the router information to
+the backup router.  When the backup router connects to the primary router
+of the cell it MUST present itself as router server in the Connection
+Authentication protocol, even though it is normal server as long as the
+primary router is available.  Reason for this is that the configuration
+needed in the responder end requires usually router connection level
+configuration.  The responder, however must understand and treat the
+connection as normal server (except when feeding router level data to
+the backup router).
+
+Backup router must know everything that the primary router knows to be
+able to take over the tasks of the primary router.  It is the primary
+router's responsibility to feed the data to the backup router.  If the
+backup router does not know all the data in the case of failure some
+connections may be lost.  The primary router of the cell must consider
+the backup router being an actual router server when it feeds the data
+to it.
+
+In addition to having direct connection to the primary router of the
+cell, the backup router must also have connection to the same router
+to which the primary router of the cell is connected.  However, it must
+not be the active router connection meaning that the backup router must
+not use that channel as its primary route and it must not notify the
+router about having connected servers, channels and clients behind it.
+It merely connects to the router.  This sort of connection is later
+referred to as being a passive connection.  Some keepalive actions may
+be needed by the router to keep the connection alive.
+
+It is required that other normal servers have passive connections to
+the backup router(s) in the cell.  Some keepalive actions may be needed
+by the server to keep the connection alive.  After they notice the
+failure of the primary router they must start using the connection to
+the first backup router as their primary route.
+
+Also, if any other router in the network is using the cell's primary
+router as its own primary router, it must also have passive connection
+to the cell's backup router.  It too is prepared to switch to use the
+backup router as its new primary router as soon as the original primary
+router becomes unresponsive.
+
+All of the parties of this protocol know which one is the backup router
+of the cell from their local configuration.  Each of the entities must
+be configured accordingly and care must be taken when configuring the
+backup routers, servers and other routers in the network.
+
+It must be noted that some of the channel messages and private messages
+may be lost during the switch to the backup router.  The announcements
+assure that the state of the network is not lost during the switch.
+
+It is RECOMMENDED that there would be at least one backup router in
+the cell.  It is NOT RECOMMENDED to have all servers in the cell acting
+as backup routers as it requires establishing several connections to
+several servers in the cell.  Large cells can easily have several
+backup routers in the cell.
+
+The order of the backup routers are decided at the local configuration
+phase.  All the parties of this protocol must be configured accordingly to
+understand the order of the backup routers.  It is not required that the
+backup server is actually an active server in the cell.  The backup router
+may be a redundant server in the cell that does not accept normal client
+connections at all.  It may be reserved purely for the backup purposes.
+
+If also the first backup router is down as well and there is another
+backup router in the cell then it will start acting as the primary
+router as described above.
+
+
+.ti 0
+3.14.1 Switching to Backup Router
+
+When the primary router of the cell becomes unresponsive, for example
+by sending EOF to the connection, all the parties of this protocol MUST
+replace the old connection to the primary router with first configured
+backup router.  The backup router usually needs to do local modifications
+to its database in order to update all the information needed to maintain
+working routes.  The backup router must understand that clients that
+were originated from the primary router are now originated from some of
+the existing server connections and must update them accordingly.  It
+must also remove those clients that were owned by the primary router
+since those connections were lost when the primary router became
+unresponsive.
+
+All the other parties of the protocol must also update their local
+database to understand that the route to the primary router will now go
+to the backup router.
+
+Servers connected to the backup router MUST send SILC_PACKET_RESUME_ROUTER
+packet with type value 21, to indicate that the server will start using
+the backup router as primary router.  The backup router MUST NOT allow
+this action if it detects that primary is still up and running.  If
+backup router knows that primary is up and running it MUST send
+SILC_PACKET_FAILURE with type value 21 (4 bytes, MSB first order) back
+to the server.  The server then MUST NOT use the backup as primary
+router, but must try to establish connection back to the primary router.
+If the action is allowed type value 21 is sent back to the server from
+the backup router.  It is RECOMMENDED that implementations use the
+SILC_COMMAND_PING command to detect whether primary router is responsive.
+
+The servers connected to the backup router must then announce their
+clients, channels, channel users, channel user modes, channel modes,
+topics and other information to the backup router.  This is to assure
+that none of the important notify packets were lost during the switch
+to the backup router.  The backup router must check which of these
+announced entities it already has and distribute the new ones to the
+primary router.
+
+The backup router too must announce its servers, clients, channels
+and other information to the new primary router.  The primary router
+of the backup router too must announce its information to the backup
+router.  Both must process only the ones they do not know about.  If
+any of the announced modes do not match then they are enforced in
+normal manner as defined in section 4.2.1 Announcing Clients, Channels
+and Servers.
+
+
+.ti 0
+3.14.2 Resuming Primary Router
+
+Usually the primary router is unresponsive only a short period of time
+and it is intended that the original router of the cell will resume
+its position as primary router when it comes back online.  The backup
+router that is now acting as primary router of the cell must constantly
+try to connect to the original primary router of the cell.  It is
+RECOMMENDED that it would try to reconnect in 30 second intervals to
+the primary router.
+
+When the connection is established to the primary router the backup
+resuming protocol is executed.  The protocol is advanced as follows:
+
+  1. Backup router sends SILC_PACKET_RESUME_ROUTER packet with type
+     value 1 to the primary router that came back online.  The packet
+     will indicate the primary router has been replaced by the backup
+     router.  After sending the packet the backup router will announce
+     all of its channels, channel users, modes etc. to the primary
+     router.
+
+     If the primary knows that it has not been replaced (for example
+     the backup itself disconnected from the primary router and thinks
+     that it is now primary in the cell) the primary router send
+     SILC_PACKET_FAILURE with the type value 1 (4 bytes, MSB first
+     order) back to the backup router.  If backup receives this it
+     MUST NOT continue with the backup resuming protocol.
+
+  2. Backup router sends SILC_PACKET_RESUME_ROUTER packet with type
+     value 1 to its current primary router to indicate that it will
+     resign as being primary router.  Then, backup router sends the
+     SILC_PACKET_RESUME_ROUTER packet with type value 1 to all
+     connected servers to also indicate that it will resign as being
+     primary router.
+
+  3. Backup router also send SILC_PACKET_RESUME_ROUTER packet with
+     type value 1 to the router that is using the backup router
+     currently as its primary router.
+
+  4. Any server and router that receives the SILC_PACKET_RESUME_ROUTER
+     with type value 1 must reconnect immediately to the primary
+     router of the cell that came back online.  After they have created
+     the connection they MUST NOT use that connection as active primary
+     route but still route all packets to the backup router.  After
+     the connection is created they MUST send SILC_PACKET_RESUME_ROUTER
+     with type value 2 back to the backup router.  The session ID value
+     found in the first packet MUST be set in this packet.
+
+  5. Backup router MUST wait for all packets with type value 2 before
+     it continues with the protocol.  It knows from the session ID values
+     set in the packet when it has received all packets.  The session
+     value should be different in all packets it has sent earlier.
+     After the packets are received the backup router sends the
+     SILC_PACKET_RESUME_ROUTER packet with type value 3 to the
+     primary router that came back online.  This packet will indicate
+     that the backup router is now ready to resign as being primary
+     router.  The session ID value in this packet MUST be the same as
+     in the first packet sent to the primary router.  During this time
+     the backup router must still route all packets it is receiving
+     from server connections.
+
+  6. The primary router receives the packet and send the packet
+     SILC_PACKET_RESUME_ROUTER with type value 4 to all connected servers
+     including the backup router.  It also sends the packet with type
+     value 4 to its primary router, and to the router that is using
+     it as its primary router.  The Session ID value in these packets
+     SHOULD be zero (0).
+
+  7. Any server and router that receives the SILC_PACKET_RESUME_ROUTER
+     packet with type value 4 must switch their primary route to the new
+     primary router and remove the route for the backup router, since
+     it is no longer the primary router of the cell.  They must also
+     update their local database to understand that the clients are
+     not originated from the backup router but from the locally connected
+     servers.  After that they MUST announce their channels, channel
+     users, modes etc. to the primary router.  They MUST NOT use the
+     backup router connection after this and the connection is considered
+     to be a passive connection.  The implementation SHOULD be able
+     to disable the connection without closing the actual link.
+
+After this protocol is executed the backup router is now again a normal
+server in the cell that has the backup link to the primary router.  The
+primary router feeds the router specific data again to the backup router.
+All server connections to the backup router are considered passive
+connections.
+
+When the primary router of the cell comes back online and connects
+to its remote primary router, the remote primary router MUST send the
+SILC_PACKET_RESUME_ROUTER packet with type value 20 indicating that the
+connection is not allowed since the router has been replaced by an
+backup router in the cell.  The session ID value in this packet SHOULD be
+zero (0).  When the primary router receives this packet it MUST NOT use
+the connection as active connection but must understand that it cannot
+act as primary router in the cell, until the backup resuming protocol has
+been executed.
+
+The following type values has been defined for SILC_PACKET_RESUME_ROUTER
+packet:
+
+  1    SILC_SERVER_BACKUP_START
+  2    SILC_SERVER_BACKUP_START_CONNECTED
+  3    SILC_SERVER_BACKUP_START_ENDING
+  4    SILC_SERVER_BACKUP_START_RESUMED
+  20   SILC_SERVER_BACKUP_START_REPLACED
+  21   SILC_SERVER_BACKUP_START_USE
+
+If any other value is found in the type field the packet MUST be
+discarded.  The SILC_PACKET_RESUME_ROUTER packet and its payload
+is defined in [SILC2].
+
+
+.ti 0
+4 SILC Procedures
+
+This section describes various SILC procedures such as how the
+connections are created and registered, how channels are created and
+so on.  The references [SILC2], [SILC3] and [SILC4] permeate this
+section's definitions.
+
+
+.ti 0
+4.1 Creating Client Connection
+
+This section describes the procedure when a client connects to SILC
+server.  When client connects to server the server MUST perform IP
+address lookup and reverse IP address lookup to assure that the origin
+host really is who it claims to be.  Client, a host, connecting to server
+SHOULD have both valid IP address and fully qualified domain name (FQDN).
+
+After that the client and server performs SILC Key Exchange protocol
+which will provide the key material used later in the communication.
+The key exchange protocol MUST be completed successfully before the
+connection registration may continue.  The SILC Key Exchange protocol
+is described in [SILC3].
+
+Typical server implementation would keep a list of connections that it
+allows to connect to the server.  The implementation would check, for
+example, the connecting client's IP address from the connection list
+before the SILC Key Exchange protocol has been started.  The reason for
+this is that if the host is not allowed to connect to the server there
+is no reason to perform the key exchange protocol.
+
+After successful key exchange protocol the client and server perform
+connection authentication protocol.  The purpose of the protocol is to
+authenticate the client connecting to the server.  Flexible
+implementation could also accept the client to connect to the server
+without explicit authentication.  However, if authentication is
+desired for a specific client it may be based on passphrase or
+public key authentication.  If authentication fails the connection
+MUST be terminated.  The connection authentication protocol is described
+in [SILC3].
+
+After successful key exchange and authentication protocol the client
+MUST register itself by sending SILC_PACKET_NEW_CLIENT packet to the
+server.  This packet includes various information about the client
+that the server uses to register the client.  Server registers the
+client and sends SILC_PACKET_NEW_ID to the client which includes the
+created Client ID that the client MUST start using after that.  After
+that all SILC packets from the client MUST have the Client ID as the
+Source ID in the SILC Packet Header, described in [SILC2].
+
+Client MUST also get the server's Server ID that is to be used as
+Destination ID in the SILC Packet Header when communicating with
+the server (for example when sending commands to the server).  The
+ID may be resolved in two ways.  Client can take the ID from an
+previously received packet from server that MUST include the ID,
+or to send SILC_COMMAND_INFO command and receive the Server ID as
+command reply.
+
+Server MAY choose not to use the information received in the
+SILC_PACKET_NEW_CLIENT packet.  For example, if public key or
+certificate were used in the authentication, server MAY use that
+information rather than what it received from client.  This is a suitable
+way to get the true information about client if it is available.
+
+The nickname of client is initially set to the username sent in the
+SILC_PACKET_NEW_CLIENT packet.  User may set the nickname to something
+more desirable by sending SILC_COMMAND_NICK command.  However, this is
+not required as part of registration process.
+
+Server MUST also distribute the information about newly registered
+client to its router (or if the server is router, to all routers in
+the SILC network).  More information about this in [SILC2].
+
+Router server MUST also check whether some client in the local cell
+is watching for the nickname this new client has, and send the
+SILC_NOTIFY_TYPE_WATCH to the watcher.
+
+
+
+
+.ti 0
+4.2 Creating Server Connection
+
+This section describes the procedure when server connects to its
+router (or when router connects to other router, the cases are
+equivalent).  The procedure is very much alike to when a client
+connects to the server thus it is not repeated here.
+
+One difference is that server MUST perform connection authentication
+protocol with proper authentication.  A proper authentication is based
+on passphrase authentication or public key authentication based on
+digital signatures.
+
+After server and router have successfully performed the key exchange
+and connection authentication protocol, the server MUST register itself
+to the router by sending SILC_PACKET_NEW_SERVER packet.  This packet
+includes the server's Server ID that it has created by itself and
+other relevant information about the server.  The router receiving the
+ID MUST verify that the IP address in the Server ID is same as the
+server's real IP address.
+
+After router has received the SILC_PACKET_NEW_SERVER packet it
+distributes the information about newly registered server to all routers
+in the SILC network.  More information about this is in [SILC2].
+
+As the client needed to resolve the destination ID this MUST be done by
+the server that connected to the router, as well.  The way to resolve it
+is to get the ID from previously received packet.  The server MAY also
+use SILC_COMMAND_INFO command to resolve the ID.  Server MUST also start
+using its own Server ID as Source ID in SILC Packet Header and the
+router's Server ID as Destination when communicating with the router.
+
+
+.ti 0
+4.2.1 Announcing Clients, Channels and Servers
+
+After server or router has connected to the remote router, and it already
+has connected clients and channels it MUST announce them to the router.
+If the server is router server, also all the local servers in the cell
+MUST be announced.
+
+All clients are announced by compiling a list of ID Payloads into the
+SILC_PACKET_NEW_ID packet.  All channels are announced by compiling a
+list of Channel Payloads into the SILC_PACKET_NEW_CHANNEL packet.
+Channels' mode, founder public key, channel public keys, and other
+channel mode specific data is announced by sending the
+SILC_NOTIFY_TYPE_CMODE_CHANGE notify list.
+
+The channel public keys that are announced are compiled in Argument
+List Payload where the argument type is 0x03, and each argument is
+Public Key Payload containing one public key or certificate.
+
+Also, the channel users on the channels must be announced by compiling
+a list of Notify Payloads with the SILC_NOTIFY_TYPE_JOIN notify type
+into the SILC_PACKET_NOTIFY packet.  The users' modes on the channel
+must also be announced by compiling list of Notify Payloads with the
+SILC_NOTIFY_TYPE_CUMODE_CHANGE notify type into the SILC_PACKET_NOTIFY
+packet.
+
+The router MUST also announce the local servers by compiling list of
+ID Payloads into the SILC_PACKET_NEW_ID packet.
+
+Also, clients' modes (user modes in SILC) MUST be announced.  This is
+done by compiling a list of Notify Payloads with SILC_NOTIFY_UMODE_CHANGE
+notify type into the SILC_PACKET_NOTIFY packet.  Also, channels' topics
+MUST be announced by compiling a list of Notify Payloads with the
+SILC_NOTIFY_TOPIC_SET notify type into the SILC_PACKET_NOTIFY packet.
+Also, channel's invite and ban lists MUST be announced by compiling list
+of Notify Payloads with the SILC_NOTIFY_TYPE_INVITE and
+SILC_NOTIFY_TYPE_BAN notify types, respectively, into the
+SILC_PACKET_NOTIFY packet.
+
+The router which receives these lists MUST process them and broadcast
+the packets to its primary router.  When processing the announced channels
+and channel users the router MUST check whether a channel exists already
+with the same name.  If channel exists with the same name it MUST check
+whether the Channel ID is different.  If the Channel ID is different the
+router MUST send the notify type SILC_NOTIFY_TYPE_CHANNEL_CHANGE to the
+server to force the channel ID change to the ID the router has.  If the
+mode of the channel is different the router MUST send the notify type
+SILC_NOTIFY_TYPE_CMODE_CHANGE to the server to force the mode change
+to the mode that the router has.
+
+The router MUST also generate new channel key and distribute it to the
+channel.  The key MUST NOT be generated if the SILC_CMODE_PRIVKEY mode
+is set.
+
+If the channel has a channel founder already on the router, the router
+MUST send the notify type SILC_NOTIFY_TYPE_CUMODE_CHANGE to the server
+to force the mode change for the channel founder on the server.  The
+channel founder privileges MUST be removed on the server.
+
+If the channel public keys are already set on the on router, the router
+MUST ignore the received channel public key list and send the notify
+type SILC_NOTIFY_TYPE_CUMODE_CHANGE to the server which includes the
+channel public key list that is on router.  The server MUST change the
+list to the one it receives from router.
+
+The router processing the channels MUST also compile a list of
+Notify Payloads with the SILC_NOTIFY_TYPE_JOIN notify type into the
+SILC_PACKET_NOTIFY and send the packet to the server.  This way the
+server (or router) will receive the clients on the channel that
+the router has.
+
+
+.ti 0
+4.3 Joining to a Channel
+
+This section describes the procedure when client joins to a channel.
+Client joins to channel by sending command SILC_COMMAND_JOIN to the
+server.  If the receiver receiving join command is normal server the
+server MUST check its local list whether this channel already exists
+locally.  This would indicate that some client connected to the server
+has already joined to the channel.  If this is the case, the client is
+joined to the channel, new channel key is created and information about
+newly joined channel is sent to the router.  The router is informed
+by sending SILC_NOTIFY_TYPE_JOIN notify type.  The notify type MUST
+also be sent to the local clients on the channel.  The new channel key
+is also sent to the router and to local clients on the channel.
+
+If the channel does not exist in the local list the client's command
+MUST be sent to the router which will then perform the actual joining
+procedure.  When server receives the reply to the command from the
+router it MUST be sent to the client which sent the command originally.
+Server will also receive the channel key from the server that it MUST
+send to the client which originally requested the join command.  The
+server MUST also save the channel key.
+
+If the receiver of the join command is router it MUST first check its
+local list whether anyone in the cell has already joined to the channel.
+If this is the case, the client is joined to the channel and reply is
+sent to the client.  If the command was sent by server the command reply
+is sent to the server which sent it.  Then the router MUST also create
+new channel key and distribute it to all clients on the channel and
+all servers that have clients on the channel.  Router MUST also send
+the SILC_NOTIFY_TYPE_JOIN notify type to local clients on the channel
+and to local servers that have clients on the channel.
+
+If the channel does not exist on the router's local list it MUST
+check the global list whether the channel exists at all.  If it does
+the client is joined to the channel as described previously.  If
+the channel does not exist the channel is created and the client
+is joined to the channel.  The channel key is also created and
+distributed as previously described.  The client joining to the created
+channel is made automatically channel founder and both channel founder
+and channel operator privileges are set for the client.
+
+If the router created the channel in the process, information about the
+new channel MUST be broadcast to all routers.  This is done by
+broadcasting SILC_PACKET_NEW_CHANNEL packet to the router's primary
+route.  When the router joins the client to the channel it MUST also
+send information about newly joined client to all routers in the SILC
+network.  This is done by broadcasting the SILC_NOTIFY_TYPE_JOIN notify
+type to the router's primary route.
+
+It is important to note that new channel key is created always when
+new client joins to channel, whether the channel has existed previously
+or not.  This way the new client on the channel is not able to decrypt
+any of the old traffic on the channel.  Client which receives the reply to
+the join command MUST start using the received Channel ID in the channel
+message communication thereafter.  Client also receives the key for the
+channel in the command reply.  Note that the channel key is never
+generated or distributed if the SILC_CMODE_PRIVKEY mode is set.
+
+
+.ti 0
+4.4 Channel Key Generation
+
+Channel keys are created by router which creates the channel by taking
+enough randomness from cryptographically strong random number generator.
+The key is generated always when channel is created, when new client
+joins a channel and after the key has expired.  Key could expire for
+example in an hour.
+
+The key MUST also be re-generated whenever some client leaves a channel.
+In this case the key is created from scratch by taking enough randomness
+from the random number generator.  After that the key is distributed to
+all clients on the channel.  However, channel keys are cell specific thus
+the key is created only on the cell where the client, which left the
+channel, exists.  While the server or router is creating the new channel
+key, no other client may join to the channel.  Messages that are sent
+while creating the new key are still processed with the old key.  After
+server has sent the SILC_PACKET_CHANNEL_KEY packet client MUST start
+using the new key.  If server creates the new key the server MUST also
+send the new key to its router.  See [SILC2] for more information about
+how channel messages must be encrypted and decrypted when router is
+processing them.
+
+If the key changes very often due to joining traffic on the channel it
+is RECOMMENDED that client implementation would cache some of the old
+channel keys for short period of time so that it is able to decrypt all
+channel messages it receives.  It is possible that on a heavy traffic
+channel a message encrypted with channel key that was just changed
+is received by client after the new key was set into use.  This is
+possible because not all clients may receive the new key at the same
+time, and may still be sending messages encrypted with the old key.
+
+When client receives the SILC_PACKET_CHANNEL_KEY packet with the
+Channel Key Payload it MUST process the key data to create encryption
+and decryption key, and to create the HMAC key that is used to compute
+the MACs of the channel messages.  The processing is as follows:
+
+  channel_key  = raw key data
+  HMAC key     = hash(raw key data)
+
+The raw key data is the key data received in the Channel Key Payload.
+The hash() function is the hash function used in the HMAC of the channel.
+Note that the server also MUST save the channel key.
+
+
+.ti 0
+4.5 Private Message Sending and Reception
+
+Private messages are sent point to point.  Client explicitly destine
+a private message to specific client that is delivered to only to that
+client.  No other client may receive the private message.  The receiver
+of the private message is destined in the SILC Packet Header as in any
+other packet as well.  The Source ID in the SILC Packet Header MUST be
+the ID of the sender of the message.
+
+If the sender of a private message does not know the receiver's Client
+ID, it MUST resolve it from server.  There are two ways to resolve the
+client ID from server; it is RECOMMENDED that client implementations
+send SILC_COMMAND_IDENTIFY command to receive the Client ID.  Client
+MAY also send SILC_COMMAND_WHOIS command to receive the Client ID.
+If the sender has received earlier a private message from the receiver
+it should have cached the Client ID from the SILC Packet Header.
+
+If server receives a private message packet which includes invalid
+destination Client ID the server MUST send SILC_NOTIFY_TYPE_ERROR
+notify to the client with error status indicating that such Client ID
+does not exist.
+
+See [SILC2] for description of private message encryption and decryption
+process.
+
+
+.ti 0
+4.6 Private Message Key Generation
+
+Private message MAY be protected with a key generated by the client.
+One way to generate private message key is to use static or pre-shared
+keys in the client implementation.  Client that wants to indicate other
+client on the network that a private message key should be set, the
+client MAY send SILC_PACKET_PRIVATE_MESSAGE_KEY packet to indicate this.
+The actual key material has to be transferred outside the SILC network,
+or it has to be pre-shared key.  The client receiving this packet knows
+that the sender wishes to use private message key in private message
+communication.  In case of static or pre-shared keys the IV used in
+the encryption SHOULD be chosen randomly.  Sending the
+SILC_PACKET_PRIVATE_MESSAGE_KEY is not mandatory, and clients may
+naturally agree to use a key without sending the packet.
+
+Another choice to use private message keys is to negotiate fresh key
+material by performing the Key Agreement.  The SILC_PACKET_KEY_AGREEMENT
+packet MAY be used to negotiate the fresh key material.  In this case
+the resulting key material is used to secure the private messages.
+Also, the IV used in encryption is used as defined in [SILC3], unless
+otherwise stated by the encryption mode used.  By performing Key
+Agreement the clients can also negotiate the cipher and HMAC to be used
+in the private message encryption and to negotiate additional security
+parameters.  The actual Key Agreement [SILC2] is performed by executing
+the SILC Key Exchange protocol [SILC3], peer to peer.  Because of NAT
+devices in the network, it might be impossible to perform the Key
+Agreement.  In this case using static or pre-shared key and sending the
+SILC_PACKET_PRIVATE_MESSAGE_KEY to indicate the use of a private message
+key is a working alternative.
+
+If the key is pre-shared key or other key material not generated by
+Key Agreement, then the key material SHOULD be processed as defined
+in [SILC3].  In the processing, however, the HASH, as defined in [SILC3]
+MUST be ignored.  After processing the key material it is employed as
+defined in [SILC3].  If the SILC_PACKET_PRIVATE_MESSAGE_KEY was sent,
+then it defines the cipher and HMAC to be used.  The hash algorithm to be
+used in the key material processing is the one that HMAC algorithm is
+defined to use.  If the SILC_PACKET_PRIVATE_MESSAGE_KEY was not sent at
+all, then the hash algorithm to be used SHOULD be SHA1.  In this case
+also, implementations SHOULD use the SILC protocol's mandatory cipher
+and HMAC in private message encryption.
+
+
+.ti 0
+4.7 Channel Message Sending and Reception
+
+Channel messages are delivered to a group of users.  The group forms a
+channel and all clients on the channel receives messages sent to the
+channel.  The Source ID in the SILC Packet Header MUST be the ID
+of the sender of the message.
+
+Channel messages are destined to a channel by specifying the Channel ID
+as Destination ID in the SILC Packet Header.  The server MUST then
+distribute the message to all clients, except to the original sender,
+on the channel by sending the channel message destined explicitly to a
+client on the channel.  However, the Destination ID MUST still remain
+as the Channel ID.
+
+If server receives a channel message packet which includes invalid
+destination Channel ID the server MUST send SILC_NOTIFY_TYPE_ERROR
+notify to the sender with error status indicating that such Channel ID
+does not exist.
+
+See the [SILC2] for description of channel message routing for router
+servers, and channel message encryption and decryption process.
+
+
+.ti 0
+4.8 Session Key Regeneration
+
+Session keys MUST be regenerated periodically, say, once in an hour.
+The re-key process is started by sending SILC_PACKET_REKEY packet to
+other end, to indicate that re-key must be performed.  The initiator
+of the connection SHOULD initiate the re-key.
+
+If perfect forward secrecy (PFS) flag was selected in the SILC Key
+Exchange protocol [SILC3] the re-key MUST cause new key exchange with
+SKE protocol.  In this case the protocol is secured with the old key
+and the protocol results to new key material.  See [SILC3] for more
+information.  After the SILC_PACKET_REKEY packet is sent the sender
+will perform the SKE protocol.
+
+If PFS flag was set the resulted key material is processed as described
+in the section Processing the Key Material in [SILC3].  The difference
+with re-key in the processing is that the initial data for the hash
+function is just the resulted key material and not the HASH as it
+is not computed at all with re-key.  Other than that, the key processing
+it equivalent to normal SKE negotiation.
+
+If PFS flag was not set, which is the default case, then re-key is done
+without executing SKE protocol.  In this case, the new key is created by
+providing the current sending encryption key to the SKE protocol's key
+processing function.  The process is described in the section Processing
+the Key Material in [SILC3].  The difference in the processing is that
+the initial data for the hash function is the current sending encryption
+key and not the SKE's KEY and HASH values.  Other than that, the key
+processing is equivalent to normal SKE negotiation.
+
+After both parties have regenerated the session key, both MUST send
+SILC_PACKET_REKEY_DONE packet to each other.  These packets are still
+secured with the old key.  After these packets, the subsequent packets
+MUST be protected with the new key.
+
+
+.ti 0
+4.9 Command Sending and Reception
+
+Client usually sends the commands in the SILC network.  In this case
+the client simply sends the command packet to server and the server
+processes it and replies with command reply packet.  See the [SILC4]
+for detailed description of all commands.
+
+However, if the server is not able to process the command, it is sent to
+the server's router.  This is case for example with commands such as
+SILC_COMMAND_JOIN and SILC_COMMAND_WHOIS commands.  However, there are
+other commands as well [SILC4].  For example, if client sends the WHOIS
+command requesting specific information about some client the server must
+send the WHOIS command to router so that all clients in SILC network are
+searched.  The router, on the other hand, sends the WHOIS command further
+to receive the exact information about the requested client.  The WHOIS
+command travels all the way to the server which owns the client and it
+replies with command reply packet.  Finally, the server which sent the
+command receives the command reply and it must be able to determine which
+client sent the original command.  The server then sends command reply to
+the client.  Implementations should have some kind of cache to handle, for
+example, WHOIS information.  Servers and routers along the route could all
+cache the information for faster referencing in the future.
+
+The commands sent by server may be sent hop by hop until someone is able
+to process the command.  However, it is preferred to destine the command
+as precisely as it is possible.  In this case, other routers en route
+MUST route the command packet by checking the true sender and true
+destination of the packet.  However, servers and routers MUST NOT route
+command reply packets to clients coming from other servers.  Client
+MUST NOT accept command reply packet originated from anyone else but
+from its own server.
+
+
+.ti 0
+4.10 Closing Connection
+
+When remote client connection is closed the server MUST send the notify
+type SILC_NOTIFY_TYPE_SIGNOFF to its primary router and to all channels
+the client was joined.  The server MUST also save the client's information
+for a period of time for history purposes.
+
+When remote server or router connection is closed the server or router
+MUST also remove all the clients that was behind the server or router
+from the SILC Network.  The server or router MUST also send the notify
+type SILC_NOTIFY_TYPE_SERVER_SIGNOFF to its primary router and to all
+local clients that are joined on the same channels with the remote
+server's or router's clients.
+
+Router server MUST also check whether some client in the local cell
+is watching for the nickname this client has, and send the
+SILC_NOTIFY_TYPE_WATCH to the watcher, unless the client which left
+the network has the SILC_UMODE_REJECT_WATCHING user mode set.
+
+
+.ti 0
+4.11 Detaching and Resuming a Session
+
+SILC protocol provides a possibility for a client to detach itself from
+the network without actually signing off from the network.  The client
+connection to the server is closed but the client remains as valid client
+in the network.  The client may then later resume its session back from
+any server in the network.
+
+When client wishes to detach from the network it MUST send the
+SILC_COMMAND_DETACH command to its server.  The server then MUST set
+SILC_UMODE_DETACHED mode to the client and send SILC_NOTIFY_UMODE_CHANGE
+notify to its primary router, which then MUST broadcast it further
+to other routers in the network.  This user mode indicates that the
+client is detached from the network.  Implementations MUST NOT use
+the SILC_UMODE_DETACHED flag to determine whether a packet can be sent
+to the client.  All packets MUST still be sent to the client even if
+client is detached from the network.  Only the server that originally
+had the active client connection is able to make the decision after it
+notices that the network connection is not active.  In this case the
+default case is to discard the packet.
+
+The SILC_UMODE_DETACHED flag cannot be set by client itself directly
+with SILC_COMMAND_UMODE command, but only implicitly by sending the
+SILC_COMMAND_DETACH command.  The flag also cannot be unset by the
+client, server or router with SILC_COMMAND_UMODE command, but only
+implicitly by sending and receiving the SILC_PACKET_RESUME_CLIENT
+packet.
+
+When the client wishes to resume its session in the SILC Network it
+connects to a server in the network, which MAY also be a different
+from the original server, and performs normal procedures regarding
+creating a connection as described in section 4.1.  After the SKE
+and the Connection Authentication protocols has been successfully
+completed the client MUST NOT send SILC_PACKET_NEW_CLIENT packet, but
+MUST send SILC_PACKET_RESUME_CLIENT packet.  This packet is used to
+perform the resuming procedure.  The packet MUST include the detached
+client's Client ID, which the client must know.  It also includes
+Authentication Payload which includes signature computed with the
+client's private key.  The signature is computed as defined in the
+section 3.9.1.  Thus, the authentication method MUST be based in
+public key authentication.
+
+When server receive the SILC_PACKET_RESUME_CLIENT packet it MUST
+do the following:  Server checks that the Client ID is valid client
+and that it has the SILC_UMODE_DETACHED mode set.  Then it verifies
+the Authentication Payload with the detached client's public key.
+If it does not have the public key it retrieves it by sending
+SILC_COMMAND_GETKEY command to the server that has the public key from
+the original client connection.  The server MUST NOT use the public
+key received in the SKE protocol for this connection.  If the
+signature is valid the server unsets the SILC_UMODE_DETACHED flag,
+and sends the SILC_PACKET_RESUME_CLIENT packet to its primary router.
+The routers MUST broadcast the packet and unset the SILC_UMODE_DETACHED
+flag when the packet is received.  If the server is router server it
+also MUST send the SILC_PACKET_RESUME_CLIENT packet to the original
+server whom owned the detached client.
+
+The servers and routers that receives the SILC_PACKET_RESUME_CLIENT
+packet MUST know whether the packet already has been received for
+the client.  It is a protocol error to attempt to resume the client
+session from more than one server.  The implementations could set
+internal flag that indicates that the client is resumed.  If router
+receive SILC_PACKET_RESUME_CLIENT packet for client that is already
+resumed the client MUST be killed from the network.  This would
+indicate that the client is attempting to resume the session more
+than once which is a protocol error.  In this case the router sends
+SILC_NOTIFY_TYPE_KILLED to the client.  All routers that detect
+the same situation MUST also send the notify for the client.
+
+The servers and routers that receive the SILC_PACKET_RESUME_CLIENT
+must also understand that the client may not be found behind the
+same server that it originally came from.  They must update their
+caches according to this.  The server that now owns the client session
+MUST check whether the Client ID of the resumed client is based
+on the server's Server ID.  If it is not it creates a new Client
+ID and send SILC_NOTIFY_TYPE_NICK_CHANGE to the network.  It MUST
+also send the channel keys of all channels that the client has
+joined to the client since it does not have them.  Whether the
+Client ID was changed or not the server MUST send SILC_PACKET_NEW_ID
+packet to the client.  Only after this is the client resumed back
+to the network and may start sending packets and messages.
+
+It is also possible that the server did not know about the global
+channels before the client resumed.  In this case it joins the client
+to the channels, generates new channel keys and distributes the keys
+to the channels as described in section 4.4.
+
+It is an implementation issue for how long servers keep detached client
+sessions.  It is RECOMMENDED that the detached sessions would be
+persistent as long as the server is running.
+
+
+.ti 0
+5 Security Considerations
+
+Security is central to the design of this protocol, and these security
+considerations permeate the specification.  Common security considerations
+such as keeping private keys truly private and using adequate lengths for
+symmetric and asymmetric keys must be followed in order to maintain the
+security of this protocol.
+
+Special attention must also be paid to the servers and routers that are
+running the SILC service.  The SILC protocol's security depends greatly
+on the security and the integrity of the servers and administrators that
+are running the service.  It is recommended that some form of registration
+is required by the server and router administrator prior to acceptance to
+the SILC Network.  Even though the SILC protocol is secure in a network
+of mutual distrust between clients, servers, routers and administrators
+of the servers, the client should be able to trust the servers they are
+using if they wish to do so.
+
+It however must be noted that if the client requires absolute security
+by not trusting any of the servers or routers in the SILC Network, it can
+be accomplished by negotiating private keys outside the SILC Network,
+either using SKE or some other key exchange protocol, or to use some
+other external means for distributing the keys.  This applies for all
+messages, private messages and channel messages.
+
+It is important to note that SILC, like any other security protocol, is
+not a foolproof system; the SILC servers and routers could very well be
+compromised.  However, to provide an acceptable level of security and
+usability for end users, the protocol uses many times session keys or
+other keys generated by the servers to secure the messages.  This is an
+intentional design feature to allow ease of use for end users.  This way
+the network is still usable, and remains encrypted even if the external
+means of distributing the keys is not working.  The implementation,
+however, may like to not follow this design feature, and may always
+negotiate the keys outside SILC network.  This is an acceptable solution
+and many times recommended.  The implementation still must be able to
+work with the server generated keys.
+
+If this is unacceptable for the client or end user, the private keys
+negotiated outside the SILC Network should always be used.  In the end
+it is the implementor's choice whether to negotiate private keys by
+default or whether to use the keys generated by the servers.
+
+It is also recommended that router operators in the SILC Network would
+form a joint forum to discuss the router and SILC Network management
+issues.  Also, router operators along with the cell's server operators
+should have a forum to discuss the cell management issues.
+
+
+.ti 0
+6 References
+
+[SILC2]      Riikonen, P., "SILC Packet Protocol", Internet Draft,
+             May 2002.
+
+[SILC3]      Riikonen, P., "SILC Key Exchange and Authentication
+             Protocols", Internet Draft, May 2002.
+
+[SILC4]      Riikonen, P., "SILC Commands", Internet Draft, May 2002.
+
+[IRC]        Oikarinen, J., and Reed D., "Internet Relay Chat Protocol",
+             RFC 1459, May 1993.
+
+[IRC-ARCH]   Kalt, C., "Internet Relay Chat: Architecture", RFC 2810,
+             April 2000.
+
+[IRC-CHAN]   Kalt, C., "Internet Relay Chat: Channel Management", RFC
+             2811, April 2000.
+
+[IRC-CLIENT] Kalt, C., "Internet Relay Chat: Client Protocol", RFC
+             2812, April 2000.
+
+[IRC-SERVER] Kalt, C., "Internet Relay Chat: Server Protocol", RFC
+             2813, April 2000.
+
+[SSH-TRANS]  Ylonen, T., et al, "SSH Transport Layer Protocol",
+             Internet Draft.
+
+[PGP]        Callas, J., et al, "OpenPGP Message Format", RFC 2440,
+             November 1998.
+
+[SPKI]       Ellison C., et al, "SPKI Certificate Theory", RFC 2693,
+             September 1999.
+
+[PKIX-Part1] Housley, R., et al, "Internet X.509 Public Key
+             Infrastructure, Certificate and CRL Profile", RFC 2459,
+             January 1999.
+
+[Schneier]   Schneier, B., "Applied Cryptography Second Edition",
+             John Wiley & Sons, New York, NY, 1996.
+
+[Menezes]    Menezes, A., et al, "Handbook of Applied Cryptography",
+             CRC Press 1997.
+
+[OAKLEY]     Orman, H., "The OAKLEY Key Determination Protocol",
+             RFC 2412, November 1998.
+
+[ISAKMP]     Maughan D., et al, "Internet Security Association and
+             Key Management Protocol (ISAKMP)", RFC 2408, November
+             1998.
+
+[IKE]        Harkins D., and Carrel D., "The Internet Key Exchange
+             (IKE)", RFC 2409, November 1998.
+
+[HMAC]       Krawczyk, H., "HMAC: Keyed-Hashing for Message
+             Authentication", RFC 2104, February 1997.
+
+[PKCS1]      Kalinski, B., and Staddon, J., "PKCS #1 RSA Cryptography
+             Specifications, Version 2.0", RFC 2437, October 1998.
+
+[RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
+             Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+[RFC3629]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 3629, November 2003.
+
+[RFC1321]    Rivest R., "The MD5 Message-Digest Algorithm", RFC 1321,
+             April 1992.
+
+[RFC3174]    Eastlake, F., et al., "US Secure Hash Algorithm 1 (SHA1)",
+             RFC 3174, September 2001.
+
+[PKCS7]      Kalinski, B., "PKCS #7: Cryptographic Message Syntax,
+             Version 1.5", RFC 2315, March 1998.
+
+[RFC2253]    Wahl, M., et al., "Lightweight Directory Access Protocol
+             (v3): UTF-8 String Representation of Distinguished Names",
+             RFC 2253, December 1997.
+
+[RFC3454]    Hoffman, P., et al., "Preparation of Internationalized
+             Strings ("stringprep")", RFC 3454, December 2002.
+
+
+.ti 0
+7 Author's Address
+
+.nf
+Pekka Riikonen
+Snellmaninkatu 34 A 15
+70100 Kuopio
+Finland
+
+EMail: priikone@iki.fi
+
+
+.ti 0
+Appendix A
+
+This appendix defines the stringprep [RFC3454] profile for string
+identifiers in SILC protocol.  Compliant implementation MUST use this
+profile to prepare the identifier strings in the SILC protocol.  The
+profile defines the following as required by [RFC3454].
+
+- Intended applicability of the profile:  the following identifiers in
+  the SILC Protocol;  nicknames, usernames, server names, hostnames, 
+  service names, algorithm names and other security property names [SILC3],
+  and SILC Public Key name.
+
+- The character repertoire that is the input and output to
+  stringprep:  Unicode 3.2 with the list of unassigned code points
+  being the Table A.1, as defined in [RFC3454].
+
+- The mapping tables used:  the following tables are used, in order,
+  as defined in [RFC3454].
+
+    Table B.1
+    Table B.2
+
+  The mandatory case folding is done using the Table B.2 which includes
+  the characters for the normalization form KC.
+
+- The Unicode normalization used:  the Unicode normalization form
+  KC is used, as defined in [RFC3454].
+
+- The prohibited characters as output:  the following tables are used
+  to prohibit characters, as defined in [RFC3454];
+
+    Table C.1.1
+    Table C.1.2
+    Table C.2.1
+    Table C.2.2
+    Table C.3
+    Table C.4
+    Table C.5
+    Table C.6
+    Table C.7
+    Table C.8
+    Table C.9
+
+- Additional prohibited characters as output:  in addition, the following
+  tables are used to prohibit characters, as defined in this document;
+
+    Appendix C
+    Appendix D
+
+- The bidirectional string testing used:  bidirectional string testing
+  is ignored in this profile.
+
+This profile is to be maintained in the IANA registry for stringprep
+profiles.  The name of this profile is "silc-identifier-prep" and this
+document defines the profile.  This document defines the first version of
+this profile.
+
+
+.ti 0
+Appendix B
+
+This appendix defines the stringprep [RFC3454] profile for channel name 
+strings in SILC protocol.  Compliant implementation MUST use this profile 
+to prepare the channel name strings in the SILC protocol.  The profile 
+defines the following as required by [RFC3454].
+
+- Intended applicability of the profile:  channel names.
+
+- The character repertoire that is the input and output to
+  stringprep:  Unicode 3.2 with the list of unassigned code points
+  being the Table A.1, as defined in [RFC3454].
+
+- The mapping tables used:  the following tables are used, in order,
+  as defined in [RFC3454].
+
+    Table B.1
+    Table B.2
+
+  The mandatory case folding is done using the Table B.2 which includes
+  the characters for the normalization form KC.
+
+- The Unicode normalization used:  the Unicode normalization form
+  KC is used, as defined in [RFC3454].
+
+- The prohibited characters as output:  the following tables are used
+  to prohibit characters, as defined in [RFC3454];
+
+    Table C.1.1
+    Table C.1.2
+    Table C.2.1
+    Table C.2.2
+    Table C.3
+    Table C.4
+    Table C.5
+    Table C.6
+    Table C.7
+    Table C.8
+    Table C.9
+
+- Additional prohibited characters as output:  in addition, the following
+  tables are used to prohibit characters, as defined in this document;
+
+    Appendix D
+
+- The bidirectional string testing used:  bidirectional string testing
+  is ignored in this profile.
+
+This profile is to be maintained in the IANA registry for stringprep
+profiles.  The name of this profile is "silc-identifier-ch-prep" and this
+document defines the profile.  This document defines the first version of
+this profile.
+
+
+.ti 0
+Appendix C
+
+This appendix defines additional prohibited characters in the identifier
+strings as defined in the stringprep profile in Appendix A.
+
+Reserved US-ASCII characters
+0021 002A 002C 003F 0040
+
+
+.ti 0
+Appendix D
+
+This appendix defines additional prohibited characters in the identifier
+strings as defined in the stringprep profile in Appendix A and Appendix B.
+Note that the prohibited character tables listed in the Appendix A and
+Appendix B may include some of the same characters listed in this 
+appendix as well.
+
+Symbol characters and other symbol like characters
+00A2-00A9 00AC 00AE 00AF 00B0 00B1 00B4 00B6 00B8 00D7 00F7
+02C2-02C5 02D2-02FF 0374 0375 0384 0385 03F6 0482 060E 060F
+06E9 06FD 06FE 09F2 09F3 09FA 0AF1 0B70 0BF3-0BFA 0E3F
+0F01-0F03 0F13-0F17 0F1A-0F1F 0F34 0F36 0F38 0FBE 0FBF
+0FC0-0FC5 0FC7-0FCF 17DB 1940 19E0-19FF 1FBD 1FBF-1FC1
+1FCD-1FCF 1FDD-1FDF 1FED-1FEF 1FFD 1FFE 2044 2052 207A-207C
+208A-208C 20A0-20B1 2100-214F 2150-218F 2190-21FF 2200-22FF
+2300-23FF 2400-243F 2440-245F 2460-24FF 2500-257F 2580-259F
+25A0-25FF 2600-26FF 2700-27BF 27C0-27EF 27F0-27FF 2800-28FF
+2900-297F 2980-29FF 2A00-2AFF 2B00-2BFF 2E9A 2EF4-2EFF
+2FF0-2FFF 303B-303D 3040 3095-3098 309F-30A0 30FF-3104
+312D-3130 318F 31B8-31FF 321D-321F 3244-325F 327C-327E
+32B1-32BF 32CC-32CF 32FF 3377-337A 33DE-33DF 33FF 4DB6-4DFF
+9FA6-9FFF A48D-A48F A4A2-A4A3 A4B4 A4C1 A4C5 A4C7-ABFF
+D7A4-D7FF FA2E-FAFF FFE0-FFEE FFFC 10000-1007F 10080-100FF
+10100-1013F 1D000-1D0FF 1D100-1D1FF 1D300-1D35F 1D400-1D7FF
+
+Other characters
+E0100-E01EF
+
+
+.ti 0
+Full Copyright Statement
+
+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.
index 2610cb23ba34be08461735a7b49472551f5c236e..a5312e248b649a028d973b4118b1e2403db5a3eb 100644 (file)
@@ -48,8 +48,9 @@ General {
        # without FQDN cannot connect to the server.
        #require_reverse_lookup = true;
 
-       # Maximum number of incoming connections allowed to this server.
-       # If more attempt to connect they will be refused.
+       # Maximum number of connections server can handle.  If you want
+       # to limit the number of incoming connections, define the
+       # connections_max in the ConnectionParams.
        connections_max = 1000;
 
        # Maximum number of incoming connections allowed per single host.
index a4677d25387ba37db1c748df9fa9c78ea121a851..18bd2dc413c926253070683118fb7f1270a1d356 100644 (file)
@@ -1,11 +1,11 @@
-manpage(SILCD) (8) (October 31 2002) (silc-server) (silc-server)
+manpage(SILCD) (8) (November 20 2003) (silc-server) (silc-server)
 
 
 manpagename(silcd) (SILC server)
 
 
 manpagesynopsis()
-bf(silcd) bf([) -f em(file) | -d | -D | -x | -h | -F | -C | -V bf(])
+bf(silcd) bf([) -f em(file) | -d | -D | -x | -h | -F | -C em(path) | -V bf(])
 
 
 manpagedescription()
@@ -13,41 +13,42 @@ Silcd is a server for SILC, Secure Internet Live Conferencing network.
 
 
 manpageoptions()
-bf(-f) em(FILE)    Read configuration from em(FILE).
+bf(-f) em(FILE)   Read configuration from em(FILE)
 
-bf(-d)         Enable debugging (Implies -F).
+bf(-d)        Enable debugging (Implies -F)
 
-bf(-D) em(LEVEL)   Enable debug messages of level em(LEVEL) and lower (Implies -F).
+bf(-D) em(LEVEL)  Enable debug messages of level em(LEVEL) and lower (Implies -F)
 
-bf(-x)         Enable hexdumps (Implies -d).
+bf(-x)        Enable hexdumps (Implies -d)
 
-bf(-F)         Don't fork.  Run silcd on foreground.
+bf(-F)        Don't fork.  Run silcd on foreground.
 
-bf(-h)         Display help message.
+bf(-h)        Display help message
 
-bf(-V)         Display version.
+bf(-V)        Display version
 
-bf(-C)         Create new public key pair. See bf(KEY GENERATION) for options.
+bf(-C) em(PATH)   Create new public key pair. See bf(KEY GENERATION) for options.
 
 manpagesection(LONG OPTIONS)
-bf(--config-file)=em(FILE)    Same as bf(-f).
+bf(--config-file)=em(FILE)      Same as bf(-f)
 
-bf(--debug)=em(STRING)        Same as bf(-d), limit to messages *em(STRING)*.
+bf(--debug)=em(STRING)          Same as bf(-d), limit to messages *em(STRING)*
 
-bf(--debug-level)=em(LEVEL)   Same as bf(-D).
+bf(--debug-level)=em(LEVEL)     Same as bf(-D)
 
-bf(--hexdump)             Same as bf(-x).
+bf(--hexdump)               Same as bf(-x)
 
-bf(--foreground)          Same as bf(-F).
+bf(--foreground)            Same as bf(-F)
 
-bf(--version)             Same as bf(-V).
+bf(--version)               Same as bf(-V)
 
-bf(--create-key-pair)     Same as bf(-C).
+bf(--create-key-pair)=em(PATH)  Same as bf(-C)
 
 
 manpagesection(KEY GENERATION)
-When generating new key pair for silcd (bf(-C)), the following extra switches
-apply:
+bf(-C) must be followed directly with a path to directory into which the
+private and public keys will be written to. When generating new key pair 
+for silcd (bf(-C)), the following extra switches apply:
 
 bf(--pkcs)=em(PKCS)       Set the public key algorithm of public key pair.  For example bf(rsa).
 
@@ -65,8 +66,8 @@ If no bf(--identifier) is used, an identifier will be created automatically.
 
 Example:
 
-bf(silcd -C --identifier)="UN=foobar, HN=foo.bar.com, RN=Foo T. Bar,
-E=foo@bar.com, C=FI"
+bf(silcd -C /etc/silcd --identifier)="UN=foobar, HN=foo.bar.com, 
+RN=Foo T. Bar, E=foo@bar.com, C=FI"
 
 
 manpagefiles()
index 9b607a0cb1c52c9fb94b9adf53977d44bfce2353..c0f69414825262bf8c241e0b232b75cc4647cbca 100644 (file)
@@ -1,4 +1,4 @@
-<!-- This file is processed with html2ps to generate PostiScript. 
+<!-- This file is processed with html2ps to generate PostiScript.
      Do not edit the HTML syntax unless you know what you are doing. -->
 <html>
 <head>
@@ -7,14 +7,14 @@
 <meta name="Author" content="Pekka Riikonen - SILC Project">
 <meta name="Description"
  content="SILC - Secure Internet Live Conferencing Protocol">
-<meta name="Created" content="Version 1.0.5 / 15 Jab 2002">
+<meta name="Created" content="Version 1.2 / 22 October 2003">
 </head>
 <body bgcolor="#ffffff">
 
 <font face="Helvetica">
 
 <font size="6"><b>SILC Protocol White Paper</b></font><br>
-<font size="2">Version 1.0.5 / 15 Jan 2002</font>
+<font size="2">Version 1.2 / 22 October 2003</font>
 
 <p>
 <h1>Introduction</h1>
@@ -28,7 +28,7 @@ protocols, such as ICQ.  However, all of these different chat protocols
 have something in common; they are all insecure.
 <p>
 
-The security is important feature in applications and protocols in 
+The security is important feature in applications and protocols in
 contemporary network environment.  The older chat protocols, however have
 failed to meet the growing security requirements on the Internet.
 It is not anymore enough to just provide services, like for example
@@ -50,8 +50,8 @@ of the SILC protocol is to provide secure conferencing services.
 
 The SILC Protocol have been developed as Open Source project.  The
 protocol specifications are freely available and they have been submitted to
-the IETF.  The very first implementations of the protocol are also already
-available.
+the IETF.  The protocol is currently stabilizing and has reached a version
+1.2.
 
 <p><br>
 <h1>About This White Paper</h1>
@@ -66,7 +66,7 @@ in this document.
 <p>
 
 <p>
-(c) Copyright 2001 - 2002 Pekka Riikonen 
+(c) Copyright 2001 - 2003 Pekka Riikonen
 (<a href="mailto:priikone at silcnet.org">priikone at silcnet.org</a>)
 <p>
 This document is free document; you can redistribute it and/or modify
@@ -82,24 +82,33 @@ See the GNU General Public License for more details.
 <h1>SILC Protocol</h1>
 <p>
 
-The Secure Internet Live Conferencing (SILC) protocol provides secure
-conferencing services over insecure network channel.  The SILC is IRC
-like protocol, however it does not support IRC.  Strong cryptographic
-methods are used to protect SILC packets inside the SILC network.  SILC
-provides all the common conferencing services like channels, channel
-messages, private messages, nicknames, various commands, and secure
-file transfer.  Difference to other chat protocol is in the design of
-the protocol.  The SILC protocol has been designed from the day one
-security in mind and it shows in the protocol design.
+Secure Internet Live Conferencing, or SILC in short, is a modern
+conferencing protocol which provides rich conferencing features with
+high security.  One of the main design principles of the protocol was
+security. Many of the SILC features are found in traditional chat
+protocols such as IRC but many of the SILC features can also be found
+in Instant Message (IM) style protocols.
+<p>
+
+SILC combines features from both of these chat protocol styles, and
+can be implemented as either IRC-like system or IM-like system. In
+fact, SILC removes the need to make such distinction between these
+two protocol styles. Some of the more advanced and security features
+of the protocol are new to all conferencing protocols. SILC also
+supports multimedia messages and can also be implemented as a
+video and audio conferencing system.  The protocol is also compact
+and robust and suites well for mobile environments where the low
+bandwidth sets special requirements for protocols.  All packet sizes
+in SILC can be even further reduced by utlizing compression.
 <p>
 
 The packets and messages in the SILC network are always encrypted and
 authenticated.  It is not possible to send unencrypted messages in SILC
 at all.  This assures that end user cannot even accidently send unencrypted
-messages while thinking that it is encrypted.  This is one of the problems 
+messages while thinking that it is encrypted.  This is one of the problems
 of most of the other chat protocols that provide so called plugin encryption.
 They are not secure by default but try to provide security by applying
-external security protocol such as PGP or SSL over the insecure chat
+external security protocol such as PGP or SSL over the insecure
 protocol.  In these cases the security is achieved usually by encrypting the
 data while key management, message authentication and other security issues
 may be left out, leaving the implementation vulnerable to various security
@@ -129,17 +138,42 @@ a key exchange protocol is executed to negotiate file transfer session
 key.
 <p>
 
-The network topology is also different to various other chat protocols,
-like for example IRC.  IRC has tree style network, but SILC network can be
-described more as an hybrid ring-mesh network.  The routers in the network
-form a ring, but they can also have other direct routers (secondary routes)
-to other routers.  A router in the network is also called a cell, when it
-has multiple servers and clients connected to it.  The cell can also have
-backup routers in case the primary router becomes unresponsive.
+The SILC protocol also supports so called detaching, a novel idea where
+it is possible to detach from the server without actually quitting the
+network.  It is then later possible to resume the connection back to some
+server in the network, and be like you were never gone.
+<p>
+
+The SILC protocol also allows distribution and exchange of public keys
+and certificates through the SILC network.  It is also possible to fetch
+detailed user information from other users through the SILC network.  It
+is possible to fetch for example users's business card, pictures,
+certificates, etc.
+<p>
+
+SILC protocol also supports services, which are extensions to the core
+protocol.  They can be used to augment the features of the protocol or
+to add entirely new features without breaking backwards compatibility.
+Services can be negotiated online and authenticated with passphrases or
+with digital signatures.
+<p>
+
+The network topology is also different from traditional conferencing and
+chat protocols.  The SILC network forms so called hybrid ring-mesh network
+at the router level, and star network at the server level.  This sort of
+network topology allows better scalability and faster delivery of packets
+than traditional spanning tree style network.  The router servers and normal
+servers also has the distinction that only router's know global information
+and keep the global network state up to date, and normal servers keep only
+local information up to date.  This significantly increases the scalability
+of the network.  The network also supports backup routers which can be
+used to protect the network against netsplits.
 
 <p><br>
 <object data="silc_network.jpg" type="application/postscript">
-<img src="silc_network.png" alt="SILC Network" align="center" border"0">
+<a href="silc_network.png">
+<img src="s_silc_network.png" alt="SILC Network" align="center" 
+border="0"></a>
 </object>
 <p><br>
 
@@ -168,13 +202,14 @@ The end user, however does not use Client IDs.  The end users usually selects
 a preferred nickname they want to use, and identifies themself with that
 nickname to other users on the network.  The nicknames are not unique in
 the SILC Network.  There can be multiple same nicknames at the same time
-on the network.  The maximum length for the nickname is 128 characters.
+on the network.  The maximum length for the nickname is 128 bytes.
 <p>
 
 Most of the other chat protocols have unique nicknames.  This is where SILC
 differs from most of the other chat protocols.  The purpose of this
 feature is to make IRC style nickname wars obsolete, as no one owns their
-nickname; there can always be somene else with the same nickname.
+nickname; there can always be somene else with the same nickname.  This
+feature also makes nickname registering services obsolete.
 <p>
 
 When client connects to the server the SILC Key Exchange (SKE) protocol and
@@ -224,7 +259,7 @@ and the SILC Connection Authentication protocol are executed, just like
 when client connects to server.  The SKE results in to the session key
 that is used to secure the communication between the server and the
 router.  The connection authentication protocol is used to authenticate
-the server to the router.  The authentication is always based in either 
+the server to the router.  The authentication is always based in either
 passphrase or public key (or certificates).
 
 
@@ -265,7 +300,9 @@ network as its primary route.
 
 <p><br>
 <object data="silc_routers.jpg" type="application/postscript">
-<img src="silc_routers.png" alt="SILC Routers" align="center" border"0">
+<a href="silc_routers.png">
+<img src="s_silc_routers.png" alt="SILC Routers" align="center" 
+border="0"></a>
 </object>
 <p><br>
 
@@ -285,8 +322,8 @@ the routers.  All the secondary routes also have their own session keys.
 <p>
 
 The basis of SILC protocol relies in the SILC packets and they are with
-out a doubt the most important part of the protocol.  The SILC Packet 
-protocol is a binary packet protocol.  The protocol provides secure
+out a doubt the most important part of the protocol.  The SILC Packet
+protocol is a secure binary packet protocol.  The protocol provides secure
 binary packets and assures that the contents of the packets are secured
 and authenticated.
 <p>
@@ -297,12 +334,14 @@ packets in SILC network are always encrypted and their integrity is
 assured by computed Message Authentication Codes (MAC).  The protocol
 defines several packet types and packet payloads.  Each packet type
 usually has a specific packet payload that actually defines the contents
-of the packet.  Hence, the actual data in the packet is the packet payload 
+of the packet.  Hence, the actual data in the packet is the packet payload
 defined in the protocol.
 
 <p><br>
 <object data="silc_packet.jpg" type="application/postscript">
-<img src="silc_packet.png" alt="Typical SILC Packet" align="center" border"0">
+<a href="silc_packet_png">
+<img src="s_silc_packet.png" alt="Typical SILC Packet" align="center" 
+border="0"></a>
 </object>
 <p><br>
 
@@ -315,7 +354,7 @@ however depends on the packet payload.  Some of the payloads are encrypted
 with the session key and some are encrypted with other keys, for example
 with channel message keys.  The SILC Packet Header is always encrypted with
 the session key.  The MAC is computed from the SILC Packet Header and the
-data area before encrypting the packet.
+data area after encryption.  This is so called Encrypt-Then-MAC order.
 
 
 <p><br>
@@ -330,7 +369,7 @@ connects to router.  And, there is no reason why it could not be executed
 between two clients too, if two clients would need to create secret key.
 The purpose of the SKE protocol is to create session keys to be used
 in current SILC session.  The SKE is based on the Diffie-Hellman key
-exchange algorithm, and is immune to for example man-in-the-middle attacks 
+exchange algorithm, and is immune to for example man-in-the-middle attacks
 by using digital signatures.
 <p>
 
@@ -370,12 +409,12 @@ connection is closed immeadiately.
 <p>
 
 The public key or certificate that is received during the SKE protocol
-must be verified.  If it is not verified it would be possible to 
+must be verified.  If it is not verified it would be possible to
 execute a man-in-the-middle attack against the SKE protocol.  If
 certificates are used they can be verified by a third party Certification
 Authority (CA).  Verifying a public key requires either confirming
 a fingerprint of the public key over phone or email, or the server
-can for example publish the fingerprint (and the public key) on some 
+can for example publish the fingerprint (and the public key) on some
 website.  In real life systems accepting the public key without
 verification, however is often desired.  In many security protocols,
 such as in SSH2, the public key is accepted without verification
@@ -404,7 +443,7 @@ created by the servers and routers itself.
 
 Since the SILC Connection Authentication protocol is always executed after
 the SKE protocol, session keys has been established already.  This means
-that all packets sent in the connection authentication protocol are encrypted 
+that all packets sent in the connection authentication protocol are encrypted
 and authenticated.
 <p>
 
@@ -415,7 +454,7 @@ to the server.  As the packet sent by, for example client, is entirely
 encrypted it is safe to send the passphrase inside the packet.
 <p>
 
-If the authentication is based to public key then, for example the client, 
+If the authentication is based to public key then, for example the client,
 signs data with its private key and sends it to the server.  The server
 then verifies this signature by using the client's public key.  The
 packet is also encrypted in the case of public key authentication.
@@ -433,7 +472,7 @@ this the client is ready to communicate in the SILC Network.
 A channel is a named group of one or more clients which will all receive
 messages addressed to that channel.  The channel is created when first
 client joins to it, and the channel ceases to exist when the last client
-leaves it.  When channel exists, any client can reference it using the 
+leaves it.  When channel exists, any client can reference it using the
 name of the channel.  Channel is a place where group of people can engage
 conversation.
 <p>
@@ -489,7 +528,9 @@ have clients on the channel and all clients that have joined the channel.
 
 <p><br>
 <object data="silc_channel.jpg" type="application/postscript">
-<img src="silc_channel.png" alt="Channel Message Delivery" align="center" border"0">
+<a href="silc_channel.png">
+<img src="s_silc_channel.png" alt="Channel Message Delivery" 
+align="center" border="0"></a>
 </object>
 <p><br>
 
@@ -573,7 +614,7 @@ same time.
 <p><br>
 <h1>Private Messages</h1>
 <p>
-Private messages are messages that are sent from one client to another 
+Private messages are messages that are sent from one client to another
 through the SILC Network.  They are private because they are not sent to
 anyone else except to the true receiver of the message.  Private messages
 can be used to engage private conversation with another client if channels
@@ -607,13 +648,15 @@ signature of each of the message using the sender's public key.
 <p>
 Sending private messages are by default secured with session keys established
 in the SKE protocol.  This means that the private message is always encrypted
-with the session key of the next receiver of the message enroute to the 
+with the session key of the next receiver of the message enroute to the
 receiving client.  This also means that the message is decrypted and
 re-encrypted everytime it is sent further to the receiving client.
 
 <p><br>
 <object data="silc_priv1.jpg" type="application/postscript">
-<img src="silc_priv1.png" alt="Basic Private Message Delivery" align="center" border"0">
+<a href="silc_priv1.png">
+<img src="s_silc_priv1.png" alt="Basic Private Message Delivery" 
+align="center" border="0"></a>
 </object>
 <p><br>
 
@@ -632,7 +675,7 @@ can be decrypted by the servers and routers that the clients may consider
 to be untrusted.
 <p>
 
-If the clients on the other hand trust the servers and routers in their 
+If the clients on the other hand trust the servers and routers in their
 SILC Network, or they do not care that servers can decrypt their messages,
 sending private messages in this way is very simple from client's point
 of view.  For servers and routers this of course means that they need
@@ -656,7 +699,9 @@ routers in the SILC network.
 
 <p><br>
 <object data="silc_priv2.jpg" type="application/postscript">
-<img src="silc_priv2.png" alt="Private Messages with Private Message Key" align="center" border"0">
+<a href="silc_priv2.png">
+<img src="s_silc_priv2.png" alt="Private Messages with Private Message 
+Key" align="center" border="0"></a>
 </object>
 <p><br>
 
@@ -691,13 +736,14 @@ that key to secure all subsequent private messages.
 <p>
 
 Using this method of private messages delivery is recommended if the
-clients cannot trust the servers and routers in the SILC Network.  The 
+clients cannot trust the servers and routers in the SILC Network.  The
 drawback is the extra phase of setting the private message key before
 starting the conversation.  However, using the SKE protocol is the
 recommended way to negotiate the private message key since it can be
 automatized and does not cause any extra tasks for end user.
 
 
+<!--
 <p><br>
 <h2>Private Message Delivery With Public Key Encryption</h2>
 <p>
@@ -735,6 +781,25 @@ the key over email, or phone call.  The clients can also fetch the
 public keys from SILC servers.  If both of the clients trust that the
 public keys are authentic using this method of private message delivery
 is very simple and recommended.
+-->
+
+
+<p><br>
+<h1>MIME Messages</h1>
+
+SILC Protocol supports MIME messages as normal channel and private 
+messages.  By using MIME messages it is possible to send for example
+images, music and video and audio stream in SILC.  Any MIME type that is
+supported by the application can be sent via SILC network.
+<p>
+
+The MIME messages are utilized by using so called Message Flags in the
+message payload that is used in SILC protocol.  The Message Flags
+indicates the recipient that the message is a MIME message and it then
+knows how to interpret the message.  Using Message Flags it possible also
+to send other kind of messages and to augment features of normal channel
+and private messages.
+
 
 
 <p><br>
@@ -767,53 +832,31 @@ possible.
 <p><br>
 <h1>Future of the Protocol</h1>
 
-The current protocol version is 1.0.  This does not mean that the protocol
-is perfect and does not need further development.  There is still features
-that are missing from the protocol, and it is clear that the protocol needs
-to mature a bit more.  There has been a talk about adding features like
-permanent channels, more wide channel founder privileges, and other similar
-features.  The network model of the protocol allows powerful routing
-capabilities, however the routing is not fully defined yet in the protocol
-and requires more in depth work.  The protocol is still in draft phase
-and is open for new features.  However, it is our intention that the
-protocol will be standardized in the future.
+The protocol has matured into the version 1.2 over the past few years.
+It has reached a level where it is the most rich featured conferencing
+protocol as of today.  It is the SILC Project's intention to standardize
+the SILC protocol in the IETF and this is where the focus is now moving.
 
 
 <p><br>
 <h1>Conclusion</h1>
 
-The Secure Internet Live Conferencing (SILC) protocol is a new generation
-chat protocol that provides all the common conferencing services with
-strong support for security.  It has wide range of security properties
-that should meet the highest levels of security requirements, while not
-forgetting easy of use.  The network topology offers new architectural
-solution with better scalability over traditional chat protocols.
+Secure Internet Live Conferencing is a modern conferencing protocol which
+provides rich conferencing features with high security.  It has a wide
+range of security properties and features that should meet the highest
+levels of security requirements, while not forgetting ease of use.  The
+network topology offers new architectural solution with better scalability
+over traditional chat protocols.
 
 
 <p><br>
 <h1>Further Information</h1>
 <p>
 More detailed information about the SILC protocol is available in the
-SILC protocol specification documents.  There exists currently four
+SILC protocol specification documents.  There exists currently six
 Internet Drafts that defines the protocol in great detail.  The Internet
-Drafts are available from the following sources but also from the
-<a href="http://www.ietf.org">IETF website</a>.
-<p>
-
-- <a href="http://silcnet.org/docs/draft-riikonen-silc-spec-04.txt">
-Secure Internet Live Conferencing (SILC), Protocol Specification</a>
-<br>
-
-- <a href="http://silcnet.org/docs/draft-riikonen-silc-pp-04.txt">
-SILC Packet Protocol</a>
-<br>
-
-- <a href="http://silcnet.org/docs/draft-riikonen-silc-ke-auth-04.txt">
-SILC Key Exchange and Authentication Protocols</a>
-<br>
-
-- <a href="http://silcnet.org/docs/draft-riikonen-silc-commands-02.txt">
-SILC Commands</a>
+Drafts are available from the <a href="http://silcnet.org">SILC Project
+website</a> but also from the <a href="http://www.ietf.org">IETF website</a>.
 <p>
 
 For comprehensive introduction to cryptography refer to the
@@ -846,7 +889,7 @@ it also means verifying the origin of a message.
 
 - Certificate
 <p>
-Certificate is a digital document which can be used to verify the 
+Certificate is a digital document which can be used to verify the
 identity of a person or host.  In SILC, certificates can be used to prove
 identity of clients, servers and routers.  Basically certificate is a public
 key with subject name.  SILC supports X.509, OpenPGP and SPKI certificates.
similarity index 65%
rename from includes/Makefile.am
rename to includes/Makefile.ad
index bf47b28ea3ccfe52f902aca8dd292edec774ba39..9abf2d80d494e81242642d5c3e6e220cc09858ad 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS = \
        silcincludes.h \
        silcwin32.h \
        silcepoc.h \
        silcbeos.h \
        silcos2.h \
-       silcversion.h \
-       version_internal.h
-endif
+       silcversion.h
+#endif SILC_DIST_TOOLKIT
 
 EXTRA_DIST = \
        silcincludes.h \
@@ -35,6 +33,5 @@ EXTRA_DIST = \
        silcepoc.h \
        silcbeos.h \
        silcos2.h \
-       silcversion.h \
-       version_internal.h \
-       silcdefs.h.in
+       silcversion.h.in \
+       silcdistdefs.h
index 65bf8bdbcf80846fa2017fbf68e8af836dc7c9ab..8e57209f31bc93dd0135729fa53c5cc1b71ff83b 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -63,6 +63,12 @@ extern "C" {
 #endif
 #endif
 
+#if defined(__MACH__) && defined(__APPLE__)
+#ifndef SILC_MACOSX
+#define SILC_MACOSX
+#endif
+#endif
+
 /* Types */
 #define SILC_SIZEOF_LONG_LONG @SILC_SIZEOF_LONG_LONG@
 #define SILC_SIZEOF_LONG @SILC_SIZEOF_LONG@
@@ -71,9 +77,15 @@ extern "C" {
 #define SILC_SIZEOF_CHAR @SILC_SIZEOF_CHAR@
 #define SILC_SIZEOF_VOID_P @SILC_SIZEOF_VOID_P@
 
-#if defined(HAVE_SILCDEFS_H) || defined(SILC_WIN32)
+/* Compilation time defines, for third-party software */
+@__SILC_HAVE_PTHREAD@
+@__SILC_HAVE_SIM@
+@__SILC_ENABLE_DEBUG@
+
+#if defined(HAVE_SILCDEFS_H)
 /* Automatically generated configuration header */
 #include "silcdefs.h"
+#include "silcdistdefs.h"
 #endif /* HAVE_SILCDEFS_H */
 
 /* Platform specific includes */
@@ -206,6 +218,10 @@ extern "C" {
 #include <langinfo.h>
 #endif
 
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
 #endif                         /* !SILC_WIN32 */
 
 #ifndef HAVE_GETOPT_LONG
@@ -231,6 +247,7 @@ extern "C" {
 #include "silchmac.h"
 #include "silcrng.h"
 #include "silcpkcs.h"
+#include "silcpkcs1.h"
 
 /* More SILC util library includes */
 #include "silcmutex.h"
@@ -243,6 +260,8 @@ extern "C" {
 #include "silcnet.h"
 #include "silcfileutil.h"
 #include "silcstrutil.h"
+#include "silcutf8.h"
+#include "silcstringprep.h"
 #include "silcutil.h"
 #include "silcconfig.h"
 #include "silcprotocol.h"
similarity index 80%
rename from includes/silcversion.h
rename to includes/silcversion.h.in
index e8959c134b85121f67d2c43ffcfdeb973fbe2c8b..86c16ba99963c9998a2c56b15fae5e12113f7c1e 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 extern "C" {
 #endif
 
-#include "version_internal.h"
+#define SILC_VERSION_STRING "@VERSION@"
+#define SILC_DIST_VERSION_STRING "@VERSION@"
+#define SILC_PROTOCOL_VERSION_STRING "SILC-1.2-@VERSION@ @PACKAGE@"
+#define SILC_NAME "SILC @PACKAGE_NAME@"
 
 /* SILC Protocol version number */
 #define SILC_PROTOCOL_VERSION_CURRENT 12
similarity index 58%
rename from lib/Makefile.am.pre
rename to lib/Makefile.ad
index fc4c150571f6aabed45d78ed14466cf66a0f1a69..5e12f56ba69bf304f692390b0e9535f5ce553026 100644 (file)
@@ -1,14 +1,13 @@
 #
 #  Makefile.am
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-COMMONDIRS = \
-       contrib \
-       silccore \
-       silccrypt \
-       silcsim \
-       silcmath \
-       silcske \
-       silcutil \
-       silcclient \
-       silcsftp
-#      zlib
-
-SUBDIRS = SILC_DISTRIBUTION_SUBDIRS
-DIST_SUBDIRS = SILC_DISTRIBUTION_SUBDIRS
-
 # SILC Library dirs
 SILCLIB_DIRS = \
        contrib \
        silccore \
        silccrypt \
+#ifdef SILC_DIST_SIM
        silcsim \
+#endif SILC_DIST_SIM
+#ifdef SILC_DIST_MATH
        silcmath \
+#endif SILC_DIST_MATH
        silcske \
        silcutil \
        silcsftp
 
+SILCLIB = libsilc.a
+
+#ifdef SILC_DIST_CLIENTLIB
 # SILC Client Library dirs
-SILCCLIENTLIB_DIRS = \
-       silcclient
+SILCCLIENTLIB_DIRS = silcclient
+SILCCLIENTLIB = libsilcclient.a
+#endif SILC_DIST_CLIENTLIB
+
+SUBDIRS = $(SILCLIB_DIRS) $(SILCCLIENTLIB_DIRS)
 
 CLEANFILES = libsilc.a libsilcclient.a
 DISTCLEANFILES = libsilc.a libsilcclient.a
 
-if SILC_DIST_CLIENT
-all:  remove libsilc.a libsilcclient.a
-else
-if SILC_DIST_TOOLKIT
-all:  remove libsilc.a libsilcclient.a
-else
-if SILC_DIST_WIN32DLL
-all:  silc.dll silcclient.dll
-else
-all:  remove libsilc.a
-endif
-endif
-endif
-
 remove:
-       -rm -rf libsilc.a
-       -rm -rf libsilcclient.a
+       -rm -f libsilc.a
+       -rm -f libsilcclient.a
+
+all:   remove $(SILCLIB) $(SILCCLIENTLIB)
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 install-exec-hook:
        -mkdir -p $(DESTDIR)$(libdir)
        -$(LIBTOOL) $(INSTALL) libsilc.la $(DESTDIR)$(libdir)/
        -$(LIBTOOL) $(INSTALL) libsilcclient.la $(DESTDIR)$(libdir)/
-else
+#else !SILC_DIST_TOOLKIT
+
+#ifdef SILC_DIST_SERVER
 install-exec-hook:
+if SILC_ENABLE_SHARED
        -mkdir -p $(libdir)
        -$(LIBTOOL) $(INSTALL) libsilc.la $(DESTDIR)$(libdir)/
        -rm -rf $(DESTDIR)$(libdir)/libsilc.a
-if SILC_DIST_CLIENT
-       -$(LIBTOOL) $(INSTALL) libsilcclient.la $(DESTDIR)$(libdir)/
-       -rm -rf $(DESTDIR)$(libdir)/libsilcclient.a
-endif
 endif
+#endif SILC_DIST_SERVER
 
-if SILC_DIST_WIN32DLL
-# WIN32 DLL generation
-silc.dll: libsilc.a
-       dllwrap --export-all --output-def silc.def --output-exp silc.exp \
-       --output-lib silc.lib --driver-name $(CC) --target i386-mingw32 \
-       -mno-cygwin -o silc.dll libsilc.a -lwsock32
-
-silcclient.dll: libsilcclient.a
-       dllwrap --export-all --output-def silcclient.def \
-       --output-lib silcclient.lib --output-exp silcclient.exp \
-       --driver-name $(CC) --target i386-mingw32 \
-       -mno-cygwin -o silcclient.dll libsilcclient.a -L. -lsilc -lwsock32
+#ifdef SILC_DIST_CLIENT
+install-exec-hook:
+if SILC_ENABLE_SHARED
+       -mkdir -p $(libdir)
+       -$(LIBTOOL) $(INSTALL) libsilc.la $(DESTDIR)$(libdir)/
+       -$(LIBTOOL) $(INSTALL) libsilcclient.la $(DESTDIR)$(libdir)/
+       -rm -rf $(DESTDIR)$(libdir)/libsilc.a
+       -rm -rf $(DESTDIR)$(libdir)/libsilcclient.a
 endif
+#endif SILC_DIST_CLIENT
+#endif SILC_DIST_TOOLKIT
 
 LIB_BASE_VERSION=@LIB_BASE_VERSION@
 LIBSILC_CURRENT=@LIBSILC_CURRENT@
 LIBSILC_REVISION=@LIBSILC_REVISION@
 LIBSILC_AGE=@LIBSILC_AGE@
-LIBSILCCLIENT_CURRENT=@LIBSILCCLIENT_CURRENT@
-LIBSILCCLIENT_REVISION=@LIBSILCCLIENT_REVISION@
-LIBSILCCLIENT_AGE=@LIBSILCCLIENT_AGE@
 
 libsilc.a:
        find $(SILCLIB_DIRS) -type f -name *.lo | xargs \
@@ -113,20 +90,22 @@ libsilc.a:
        -version-info $(LIBSILC_CURRENT):$(LIBSILC_REVISION):$(LIBSILC_AGE) \
        -release $(LIB_BASE_VERSION) -rpath $(DESTDIR)$(libdir) -o libsilc.la
 
+#ifdef SILC_DIST_CLIENTLIB
+LIBSILCCLIENT_CURRENT=@LIBSILCCLIENT_CURRENT@
+LIBSILCCLIENT_REVISION=@LIBSILCCLIENT_REVISION@
+LIBSILCCLIENT_AGE=@LIBSILCCLIENT_AGE@
+
 libsilcclient.a:
        find $(SILCCLIENTLIB_DIRS) -type f -name *.lo | xargs \
        $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) \
        -version-info $(LIBSILCCLIENT_CURRENT):$(LIBSILCCLIENT_REVISION):$(LIBSILCCLIENT_AGE) \
        -release $(LIB_BASE_VERSION) -rpath $(DESTDIR)$(libdir) -o libsilcclient.la
+#endif SILC_DIST_CLIENTLIB
 
-if SILC_DIST_TOOLKIT
-SILC_EXTRA_DIST = doc
-else
-if SILC_DIST_SERVER
-SILC_EXTRA_DIST = 
-else
-SILC_EXTRA_DIST =
-endif
-endif
+#ifdef SILC_DIST_TOOLKIT
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = silc.pc silcclient.pc
+
+EXTRA_DIST = doc silc.pc.in silcclient.pc.in
+#endif SILC_DIST_TOOLKIT
 
-EXTRA_DIST = $(SILC_EXTRA_DIST)
diff --git a/lib/configure.ad b/lib/configure.ad
new file mode 100644 (file)
index 0000000..9433d0b
--- /dev/null
@@ -0,0 +1,152 @@
+#ifdef SILC_DIST_LIB
+#
+#  lib/configure.ad
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+if test x$compile_libs = xtrue; then
+
+##
+## Will compile included libs
+##
+AC_MSG_NOTICE([Configuring SILC libraries])
+
+# SILC Library directories
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/contrib"
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silccore"
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silccrypt"
+#ifdef SILC_DIST_MATH
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcmath"
+#ifdef SILC_DIST_MPI
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcmath/mpi"
+#endif SILC_DIST_MPI
+#endif SILC_DIST_MATH
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcske"
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcutil"
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcsftp"
+#ifdef SILC_DIST_SIM
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcsim"
+#endif SILC_DIST_SIM
+#ifdef SILC_DIST_CLIENT
+SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcclient"
+#endif SILC_DIST_CLIENT
+
+##
+## Library versioning.
+##
+# Do the releases and library versioning according to following rules:
+#
+#  - If any code has changed in library, increment [LIB]_REVISION
+#  - If functions were added, set [LIB]_REVISION to 0
+#  - If functions were added, removed or changed, increment [LIB]_CURRENT
+#  - If functions were added, increment [LIB]_AGE
+#  - If functions were removed, set [LIB]_AGE to 0
+#
+# where [LIB] is LIBSILC and LIBSILCCLIENT, and where "functions" means
+# functions public interfaces.
+#
+# The LIB_BASE_VERSION defines the SILC software major.minor version and
+# it is increment only when these version numbers actually change.
+#
+
+# Base version for libraries.  Do not change this unless SILC version
+# changes too.
+LIB_BASE_VERSION=1.0
+
+# libsilc versions
+LIBSILC_CURRENT=4              # prev = 3
+LIBSILC_REVISION=0             # prev = 0
+LIBSILC_AGE=3                  # prev = 2
+
+# libsilcclient versions
+LIBSILCCLIENT_CURRENT=3                # prev = 3
+LIBSILCCLIENT_REVISION=1       # prev = 0
+LIBSILCCLIENT_AGE=2            # prev = 2
+
+# Substitute the version numbers
+AC_SUBST(LIB_BASE_VERSION)
+AC_SUBST(LIBSILC_CURRENT)
+AC_SUBST(LIBSILC_REVISION)
+AC_SUBST(LIBSILC_AGE)
+AC_SUBST(LIBSILCCLIENT_CURRENT)
+AC_SUBST(LIBSILCCLIENT_REVISION)
+AC_SUBST(LIBSILCCLIENT_AGE)
+
+# Make enable-shared aware
+AM_CONDITIONAL(SILC_ENABLE_SHARED, test "$enable_shared" = yes)
+
+# Stack trace checking
+#
+AC_MSG_CHECKING(whether to enable stack tracing)
+AC_ARG_ENABLE(stack-trace,
+  [  --enable-stack-trace    enable memory stack trace],
+  [
+    case "${enableval}" in
+    yes)
+      AC_MSG_RESULT(yes)
+      AC_DEFINE([SILC_STACKTRACE], [], [SILC_STACKTRACE])
+      ;;
+    *)
+      AC_MSG_RESULT(no)
+      ;;
+    esac
+  ],
+    AC_MSG_RESULT(no)
+  )
+
+#
+# Makefile outputs
+#
+AC_CONFIG_FILES(
+lib/Makefile
+lib/contrib/Makefile
+lib/silccore/Makefile
+lib/silccrypt/Makefile
+#ifdef SILC_DIST_SIM
+lib/silcsim/Makefile
+#endif SILC_DIST_SIM
+lib/silcske/Makefile
+lib/silcutil/Makefile
+lib/silcutil/unix/Makefile
+lib/silcutil/win32/Makefile
+lib/silcutil/beos/Makefile
+lib/silcutil/os2/Makefile
+lib/silcutil/epoc/Makefile
+#ifdef SILC_DIST_MATH
+lib/silcmath/Makefile
+#endif SILC_DIST_MATH
+lib/silcsftp/Makefile
+#ifdef SILC_DIST_INPLACE
+lib/silcutil/tests/Makefile
+lib/silccrypt/tests/Makefile
+lib/silccore/tests/Makefile
+lib/silcsftp/tests/Makefile
+#endif SILC_DIST_INPLACE
+)
+
+#ifdef SILC_DIST_TOOLKIT
+AC_CONFIG_FILES(
+lib/silc.pc
+lib/silcclient.pc
+)
+#endif SILC_DIST_TOOLKIT
+
+#ifdef SILC_DIST_CLIENTLIB
+AC_CONFIG_FILES(lib/silcclient/Makefile)
+#endif SILC_DIST_CLIENTLIB
+
+fi     # compile_libs
+
+#endif SILC_DIST_LIB
index b7bec728e1b63e1d8a01b34e39adf8a95b428f6e..74faaf72f5c3c2496684e4d6f0337fa34ea2aab5 100644 (file)
@@ -1,14 +1,13 @@
 #
 #  Makefile.am
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -32,16 +31,12 @@ else
 REGEX = regex.c
 endif
 
+STRINGPREP = nfkc.c rfc3454.c stringprep.c
+
 if SILC_WIN32
-libcontrib_la_SOURCES =
+libcontrib_la_SOURCES = $(STRINGPREP)
 else
-libcontrib_la_SOURCES = \
-       $(GETOPT) \
-       $(REGEX)
-endif
-
-if SILC_DIST_TOOLKIT
-include_HEADERS = getopt.h regex.h
+libcontrib_la_SOURCES = $(STRINGPREP) $(GETOPT) $(REGEX)
 endif
 
 EXTRA_DIST = *.c *.h
diff --git a/lib/contrib/gunicomp.h b/lib/contrib/gunicomp.h
new file mode 100644 (file)
index 0000000..b5fa880
--- /dev/null
@@ -0,0 +1,661 @@
+/* This file is automatically generated.  DO NOT EDIT!
+   Instead, edit gen-unicode-tables.pl and re-run.  */
+
+#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 }
+};
diff --git a/lib/contrib/gunidecomp.h b/lib/contrib/gunidecomp.h
new file mode 100644 (file)
index 0000000..1c48c21
--- /dev/null
@@ -0,0 +1,10363 @@
+/* This file is automatically generated.  DO NOT EDIT!
+   Instead, edit gen-unicode-tables.pl and re-run.  */
+
+#ifndef DECOMP_H
+#define DECOMP_H
+
+#define G_UNICODE_LAST_CHAR 0x10ffff
+
+#define G_UNICODE_MAX_TABLE_INDEX (0x110000 / 256)
+
+#define G_UNICODE_LAST_CHAR_PART1 0x2FAFF
+
+#define G_UNICODE_LAST_PAGE_PART1 762
+
+#define G_UNICODE_NOT_PRESENT_OFFSET 65535
+
+static const guchar cclass_data[][256] = {
+  { /* page 3, index 0 */
+    230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 
+    230, 230, 230, 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 
+    220, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 
+    220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 1, 1, 1, 1, 1, 220, 
+    220, 220, 220, 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 
+    220, 220, 230, 230, 230, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 234, 234, 233, 230, 230, 230, 230, 230, 230, 230, 230, 230, 
+    230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 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 1 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 5, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 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, 230, 230, 230, 230, 220, 230, 230, 230, 222, 220, 230, 230, 230, 
+    230, 230, 230, 0, 220, 220, 220, 220, 220, 230, 230, 220, 230, 230, 222, 
+    228, 230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 20, 21, 22, 0, 23, 
+    0, 24, 25, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 6, index 3 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 230, 230, 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, 35, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 230, 230, 230, 230, 220, 
+    230, 0, 0, 230, 230, 0, 220, 230, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0
+  },
+  { /* page 7, index 4 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    230, 220, 230, 230, 220, 230, 230, 220, 220, 220, 230, 220, 220, 230, 
+    220, 230, 230, 230, 220, 230, 220, 230, 220, 230, 220, 230, 230, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 9, 0, 0, 0, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
+  },
+  { /* page 10, 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, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
+  },
+  { /* 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, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
+  },
+  { /* 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, 0, 0, 
+    0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
+  },
+  { /* 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
+  },
+  { /* page 14, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 103, 103, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 107, 107, 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 15, 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, 
+    220, 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, 220, 0, 220, 0, 216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 130, 0, 
+    132, 0, 0, 0, 0, 0, 130, 130, 130, 130, 0, 0, 130, 0, 230, 230, 9, 0, 
+    230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
+  },
+  { /* page 16, index 12 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 7, 0, 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, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 23, index 13 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 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, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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
+  },
+  { /* page 24, index 14 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 32, 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, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 1, 1, 230, 230, 
+    230, 230, 1, 1, 1, 230, 230, 0, 0, 0, 0, 230, 0, 0, 0, 1, 1, 230, 220, 
+    230, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+  },
+  { /* page 48, index 16 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 228, 232, 222, 
+    224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 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, 0, 0, 0, 0, 0, 0, 0, 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 251, index 17 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 254, index 18 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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 465, index 19 */
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 216, 216, 1, 1, 1, 0, 0, 0, 226, 216, 216, 216, 216, 216, 
+    0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 220, 220, 220, 220, 220, 0, 0, 
+    230, 230, 230, 230, 230, 220, 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, 230, 230, 230, 230, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
+    0, 0, 0, 0, 0, 0, 0, 0, 0
+  }
+};
+
+static const gint16 combining_class_table_part1[763] = {
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  0 /* page 3 */,
+  1 /* page 4 */,
+  2 /* page 5 */,
+  3 /* page 6 */,
+  4 /* page 7 */,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  5 /* page 9 */,
+  6 /* page 10 */,
+  7 /* page 11 */,
+  8 /* page 12 */,
+  9 /* page 13 */,
+  10 /* page 14 */,
+  11 /* page 15 */,
+  12 /* 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,
+  13 /* page 23 */,
+  14 /* page 24 */,
+  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 32 */,
+  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,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  16 /* page 48 */,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  17 /* page 251 */,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  18 /* page 254 */,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  0 + G_UNICODE_MAX_TABLE_INDEX,
+  19 /* page 465 */,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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
+};
+
+static const gint16 combining_class_table_part2[768] = {
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  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,
+  0 + G_UNICODE_MAX_TABLE_INDEX
+};
+
+typedef struct
+{
+  gunichar ch;
+  guint16 canon_offset;
+  guint16 compat_offset;
+} decomposition;
+
+static const decomposition decomp_table[] =
+{
+  { 0x00a0, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x00a8, G_UNICODE_NOT_PRESENT_OFFSET, 2 },
+  { 0x00aa, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x00af, G_UNICODE_NOT_PRESENT_OFFSET, 8 },
+  { 0x00b2, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x00b3, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x00b4, G_UNICODE_NOT_PRESENT_OFFSET, 16 },
+  { 0x00b5, G_UNICODE_NOT_PRESENT_OFFSET, 20 },
+  { 0x00b8, G_UNICODE_NOT_PRESENT_OFFSET, 23 },
+  { 0x00b9, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x00ba, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x00bc, G_UNICODE_NOT_PRESENT_OFFSET, 31 },
+  { 0x00bd, G_UNICODE_NOT_PRESENT_OFFSET, 37 },
+  { 0x00be, G_UNICODE_NOT_PRESENT_OFFSET, 43 },
+  { 0x00c0, 49, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c1, 53, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c2, 57, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c3, 61, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c4, 65, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c5, 69, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c7, 73, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c8, 77, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00c9, 81, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ca, 85, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00cb, 89, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00cc, 93, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00cd, 97, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ce, 101, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00cf, 105, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00d1, 109, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00d2, 113, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00d3, 117, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00d4, 121, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00d5, 125, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00d6, 129, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00d9, 133, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00da, 137, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00db, 141, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00dc, 145, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00dd, 149, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e0, 153, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e1, 157, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e2, 161, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e3, 165, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e4, 169, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e5, 173, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e7, 177, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e8, 181, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00e9, 185, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ea, 189, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00eb, 193, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ec, 197, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ed, 201, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ee, 205, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ef, 209, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00f1, 213, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00f2, 217, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00f3, 221, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00f4, 225, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00f5, 229, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00f6, 233, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00f9, 237, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00fa, 241, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00fb, 245, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00fc, 249, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00fd, 253, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x00ff, 257, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0100, 261, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0101, 265, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0102, 269, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0103, 273, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0104, 277, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0105, 281, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0106, 285, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0107, 289, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0108, 293, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0109, 297, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x010a, 301, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x010b, 305, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x010c, 309, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x010d, 313, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x010e, 317, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x010f, 321, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0112, 325, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0113, 329, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0114, 333, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0115, 337, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0116, 341, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0117, 345, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0118, 349, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0119, 353, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x011a, 357, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x011b, 361, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x011c, 365, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x011d, 369, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x011e, 373, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x011f, 377, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0120, 381, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0121, 385, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0122, 389, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0123, 393, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0124, 397, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0125, 401, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0128, 405, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0129, 409, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x012a, 413, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x012b, 417, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x012c, 421, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x012d, 425, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x012e, 429, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x012f, 433, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0130, 437, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0132, G_UNICODE_NOT_PRESENT_OFFSET, 441 },
+  { 0x0133, G_UNICODE_NOT_PRESENT_OFFSET, 444 },
+  { 0x0134, 447, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0135, 451, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0136, 455, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0137, 459, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0139, 463, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x013a, 467, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x013b, 471, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x013c, 475, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x013d, 479, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x013e, 483, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x013f, G_UNICODE_NOT_PRESENT_OFFSET, 487 },
+  { 0x0140, G_UNICODE_NOT_PRESENT_OFFSET, 491 },
+  { 0x0143, 495, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0144, 499, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0145, 503, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0146, 507, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0147, 511, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0148, 515, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0149, G_UNICODE_NOT_PRESENT_OFFSET, 519 },
+  { 0x014c, 523, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x014d, 527, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x014e, 531, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x014f, 535, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0150, 539, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0151, 543, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0154, 547, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0155, 551, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0156, 555, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0157, 559, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0158, 563, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0159, 567, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x015a, 571, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x015b, 575, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x015c, 579, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x015d, 583, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x015e, 587, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x015f, 591, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0160, 595, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0161, 599, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0162, 603, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0163, 607, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0164, 611, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0165, 615, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0168, 619, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0169, 623, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x016a, 627, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x016b, 631, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x016c, 635, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x016d, 639, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x016e, 643, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x016f, 647, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0170, 651, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0171, 655, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0172, 659, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0173, 663, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0174, 667, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0175, 671, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0176, 675, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0177, 679, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0178, 683, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0179, 687, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x017a, 691, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x017b, 695, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x017c, 699, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x017d, 703, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x017e, 707, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x017f, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x01a0, 713, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01a1, 717, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01af, 721, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01b0, 725, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01c4, G_UNICODE_NOT_PRESENT_OFFSET, 729 },
+  { 0x01c5, G_UNICODE_NOT_PRESENT_OFFSET, 734 },
+  { 0x01c6, G_UNICODE_NOT_PRESENT_OFFSET, 739 },
+  { 0x01c7, G_UNICODE_NOT_PRESENT_OFFSET, 744 },
+  { 0x01c8, G_UNICODE_NOT_PRESENT_OFFSET, 747 },
+  { 0x01c9, G_UNICODE_NOT_PRESENT_OFFSET, 750 },
+  { 0x01ca, G_UNICODE_NOT_PRESENT_OFFSET, 753 },
+  { 0x01cb, G_UNICODE_NOT_PRESENT_OFFSET, 756 },
+  { 0x01cc, G_UNICODE_NOT_PRESENT_OFFSET, 759 },
+  { 0x01cd, 762, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01ce, 766, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01cf, 770, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d0, 774, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d1, 778, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d2, 782, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d3, 786, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d4, 790, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d5, 794, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d6, 800, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d7, 806, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d8, 812, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01d9, 818, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01da, 824, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01db, 830, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01dc, 836, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01de, 842, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01df, 848, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e0, 854, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e1, 860, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e2, 866, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e3, 871, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e6, 876, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e7, 880, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e8, 884, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01e9, 888, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01ea, 892, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01eb, 896, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01ec, 900, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01ed, 906, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01ee, 912, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01ef, 917, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01f0, 922, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01f1, G_UNICODE_NOT_PRESENT_OFFSET, 926 },
+  { 0x01f2, G_UNICODE_NOT_PRESENT_OFFSET, 929 },
+  { 0x01f3, G_UNICODE_NOT_PRESENT_OFFSET, 932 },
+  { 0x01f4, 935, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01f5, 939, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01f8, 943, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01f9, 947, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01fa, 951, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01fb, 957, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01fc, 963, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01fd, 968, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01fe, 973, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x01ff, 978, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0200, 983, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0201, 987, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0202, 991, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0203, 995, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0204, 999, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0205, 1003, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0206, 1007, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0207, 1011, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0208, 1015, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0209, 1019, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x020a, 1023, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x020b, 1027, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x020c, 1031, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x020d, 1035, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x020e, 1039, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x020f, 1043, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0210, 1047, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0211, 1051, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0212, 1055, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0213, 1059, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0214, 1063, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0215, 1067, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0216, 1071, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0217, 1075, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0218, 1079, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0219, 1083, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x021a, 1087, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x021b, 1091, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x021e, 1095, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x021f, 1099, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0226, 1103, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0227, 1107, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0228, 1111, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0229, 1115, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x022a, 1119, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x022b, 1125, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x022c, 1131, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x022d, 1137, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x022e, 1143, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x022f, 1147, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0230, 1151, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0231, 1157, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0232, 1163, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0233, 1167, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x02b0, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x02b1, G_UNICODE_NOT_PRESENT_OFFSET, 1173 },
+  { 0x02b2, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x02b3, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x02b4, G_UNICODE_NOT_PRESENT_OFFSET, 1180 },
+  { 0x02b5, G_UNICODE_NOT_PRESENT_OFFSET, 1183 },
+  { 0x02b6, G_UNICODE_NOT_PRESENT_OFFSET, 1186 },
+  { 0x02b7, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x02b8, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x02d8, G_UNICODE_NOT_PRESENT_OFFSET, 1193 },
+  { 0x02d9, G_UNICODE_NOT_PRESENT_OFFSET, 1197 },
+  { 0x02da, G_UNICODE_NOT_PRESENT_OFFSET, 1201 },
+  { 0x02db, G_UNICODE_NOT_PRESENT_OFFSET, 1205 },
+  { 0x02dc, G_UNICODE_NOT_PRESENT_OFFSET, 1209 },
+  { 0x02dd, G_UNICODE_NOT_PRESENT_OFFSET, 1213 },
+  { 0x02e0, G_UNICODE_NOT_PRESENT_OFFSET, 1217 },
+  { 0x02e1, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x02e2, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x02e3, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x02e4, G_UNICODE_NOT_PRESENT_OFFSET, 1224 },
+  { 0x0340, 1227, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0341, 1230, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0343, 1233, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0344, 1236, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0374, 1241, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x037a, G_UNICODE_NOT_PRESENT_OFFSET, 1244 },
+  { 0x037e, 1248, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0384, G_UNICODE_NOT_PRESENT_OFFSET, 16 },
+  { 0x0385, 1250, 1255 },
+  { 0x0386, 1261, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0387, 1266, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0388, 1269, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0389, 1274, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x038a, 1279, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x038c, 1284, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x038e, 1289, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x038f, 1294, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0390, 1299, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03aa, 1306, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03ab, 1311, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03ac, 1316, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03ad, 1321, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03ae, 1326, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03af, 1331, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03b0, 1336, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03ca, 1343, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03cb, 1348, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03cc, 1353, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03cd, 1358, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03ce, 1363, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x03d0, G_UNICODE_NOT_PRESENT_OFFSET, 1368 },
+  { 0x03d1, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x03d2, G_UNICODE_NOT_PRESENT_OFFSET, 1374 },
+  { 0x03d3, 1377, 1289 },
+  { 0x03d4, 1382, 1311 },
+  { 0x03d5, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x03d6, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x03f0, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x03f1, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x03f2, G_UNICODE_NOT_PRESENT_OFFSET, 1399 },
+  { 0x03f4, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x03f5, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x0400, 1408, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0401, 1413, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0403, 1418, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0407, 1423, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x040c, 1428, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x040d, 1433, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x040e, 1438, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0419, 1443, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0439, 1448, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0450, 1453, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0451, 1458, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0453, 1463, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0457, 1468, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x045c, 1473, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x045d, 1478, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x045e, 1483, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0476, 1488, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0477, 1493, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04c1, 1498, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04c2, 1503, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04d0, 1508, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04d1, 1513, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04d2, 1518, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04d3, 1523, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04d6, 1528, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04d7, 1533, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04da, 1538, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04db, 1543, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04dc, 1548, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04dd, 1553, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04de, 1558, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04df, 1563, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04e2, 1568, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04e3, 1573, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04e4, 1578, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04e5, 1583, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04e6, 1588, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04e7, 1593, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04ea, 1598, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04eb, 1603, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04ec, 1608, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04ed, 1613, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04ee, 1618, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04ef, 1623, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f0, 1628, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f1, 1633, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f2, 1638, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f3, 1643, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f4, 1648, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f5, 1653, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f8, 1658, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x04f9, 1663, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0587, G_UNICODE_NOT_PRESENT_OFFSET, 1668 },
+  { 0x0622, 1673, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0623, 1678, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0624, 1683, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0625, 1688, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0626, 1693, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0675, G_UNICODE_NOT_PRESENT_OFFSET, 1698 },
+  { 0x0676, G_UNICODE_NOT_PRESENT_OFFSET, 1703 },
+  { 0x0677, G_UNICODE_NOT_PRESENT_OFFSET, 1708 },
+  { 0x0678, G_UNICODE_NOT_PRESENT_OFFSET, 1713 },
+  { 0x06c0, 1718, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x06c2, 1723, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x06d3, 1728, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0929, 1733, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0931, 1740, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0934, 1747, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0958, 1754, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0959, 1761, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x095a, 1768, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x095b, 1775, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x095c, 1782, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x095d, 1789, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x095e, 1796, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x095f, 1803, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x09cb, 1810, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x09cc, 1817, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x09dc, 1824, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x09dd, 1831, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x09df, 1838, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0a33, 1845, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0a36, 1852, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0a59, 1859, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0a5a, 1866, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0a5b, 1873, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0a5e, 1880, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0b48, 1887, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0b4b, 1894, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0b4c, 1901, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0b5c, 1908, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0b5d, 1915, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0b94, 1922, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0bca, 1929, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0bcb, 1936, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0bcc, 1943, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0c48, 1950, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0cc0, 1957, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0cc7, 1964, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0cc8, 1971, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0cca, 1978, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0ccb, 1985, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0d4a, 1995, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0d4b, 2002, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0d4c, 2009, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0dda, 2016, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0ddc, 2023, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0ddd, 2030, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0dde, 2040, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0e33, G_UNICODE_NOT_PRESENT_OFFSET, 2047 },
+  { 0x0eb3, G_UNICODE_NOT_PRESENT_OFFSET, 2054 },
+  { 0x0edc, G_UNICODE_NOT_PRESENT_OFFSET, 2061 },
+  { 0x0edd, G_UNICODE_NOT_PRESENT_OFFSET, 2068 },
+  { 0x0f0c, G_UNICODE_NOT_PRESENT_OFFSET, 2075 },
+  { 0x0f43, 2079, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f4d, 2086, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f52, 2093, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f57, 2100, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f5c, 2107, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f69, 2114, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f73, 2121, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f75, 2128, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f76, 2135, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f77, G_UNICODE_NOT_PRESENT_OFFSET, 2142 },
+  { 0x0f78, 2152, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f79, G_UNICODE_NOT_PRESENT_OFFSET, 2159 },
+  { 0x0f81, 2169, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f93, 2176, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0f9d, 2183, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0fa2, 2190, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0fa7, 2197, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0fac, 2204, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x0fb9, 2211, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1026, 2218, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e00, 2225, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e01, 2229, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e02, 2233, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e03, 2237, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e04, 2241, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e05, 2245, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e06, 2249, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e07, 2253, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e08, 2257, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e09, 2263, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e0a, 2269, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e0b, 2273, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e0c, 2277, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e0d, 2281, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e0e, 2285, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e0f, 2289, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e10, 2293, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e11, 2297, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e12, 2301, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e13, 2305, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e14, 2309, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e15, 2315, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e16, 2321, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e17, 2327, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e18, 2333, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e19, 2337, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e1a, 2341, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e1b, 2345, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e1c, 2349, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e1d, 2355, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e1e, 2361, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e1f, 2365, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e20, 2369, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e21, 2373, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e22, 2377, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e23, 2381, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e24, 2385, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e25, 2389, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e26, 2393, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e27, 2397, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e28, 2401, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e29, 2405, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e2a, 2409, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e2b, 2413, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e2c, 2417, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e2d, 2421, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e2e, 2425, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e2f, 2431, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e30, 2437, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e31, 2441, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e32, 2445, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e33, 2449, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e34, 2453, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e35, 2457, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e36, 2461, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e37, 2465, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e38, 2469, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e39, 2475, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e3a, 2481, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e3b, 2485, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e3c, 2489, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e3d, 2493, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e3e, 2497, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e3f, 2501, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e40, 2505, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e41, 2509, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e42, 2513, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e43, 2517, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e44, 2521, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e45, 2525, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e46, 2529, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e47, 2533, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e48, 2537, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e49, 2541, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e4a, 2545, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e4b, 2549, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e4c, 2553, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e4d, 2559, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e4e, 2565, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e4f, 2571, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e50, 2577, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e51, 2583, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e52, 2589, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e53, 2595, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e54, 2601, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e55, 2605, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e56, 2609, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e57, 2613, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e58, 2617, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e59, 2621, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e5a, 2625, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e5b, 2629, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e5c, 2633, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e5d, 2639, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e5e, 2645, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e5f, 2649, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e60, 2653, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e61, 2657, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e62, 2661, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e63, 2665, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e64, 2669, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e65, 2675, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e66, 2681, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e67, 2687, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e68, 2693, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e69, 2699, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e6a, 2705, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e6b, 2709, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e6c, 2713, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e6d, 2717, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e6e, 2721, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e6f, 2725, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e70, 2729, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e71, 2733, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e72, 2737, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e73, 2741, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e74, 2745, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e75, 2749, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e76, 2753, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e77, 2757, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e78, 2761, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e79, 2767, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e7a, 2773, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e7b, 2779, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e7c, 2785, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e7d, 2789, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e7e, 2793, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e7f, 2797, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e80, 2801, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e81, 2805, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e82, 2809, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e83, 2813, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e84, 2817, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e85, 2821, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e86, 2825, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e87, 2829, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e88, 2833, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e89, 2837, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e8a, 2841, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e8b, 2845, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e8c, 2849, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e8d, 2853, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e8e, 2857, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e8f, 2861, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e90, 2865, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e91, 2869, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e92, 2873, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e93, 2877, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e94, 2881, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e95, 2885, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e96, 2889, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e97, 2893, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e98, 2897, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e99, 2901, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1e9a, G_UNICODE_NOT_PRESENT_OFFSET, 2905 },
+  { 0x1e9b, 2909, 2657 },
+  { 0x1ea0, 2914, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea1, 2918, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea2, 2922, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea3, 2926, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea4, 2930, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea5, 2936, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea6, 2942, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea7, 2948, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea8, 2954, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ea9, 2960, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eaa, 2966, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eab, 2972, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eac, 2978, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ead, 2984, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eae, 2990, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eaf, 2996, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb0, 3002, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb1, 3008, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb2, 3014, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb3, 3020, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb4, 3026, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb5, 3032, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb6, 3038, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb7, 3044, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb8, 3050, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eb9, 3054, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eba, 3058, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ebb, 3062, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ebc, 3066, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ebd, 3070, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ebe, 3074, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ebf, 3080, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec0, 3086, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec1, 3092, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec2, 3098, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec3, 3104, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec4, 3110, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec5, 3116, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec6, 3122, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec7, 3128, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec8, 3134, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ec9, 3138, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eca, 3142, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ecb, 3146, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ecc, 3150, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ecd, 3154, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ece, 3158, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ecf, 3162, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed0, 3166, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed1, 3172, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed2, 3178, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed3, 3184, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed4, 3190, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed5, 3196, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed6, 3202, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed7, 3208, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed8, 3214, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ed9, 3220, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eda, 3226, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1edb, 3232, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1edc, 3238, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1edd, 3244, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ede, 3250, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1edf, 3256, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee0, 3262, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee1, 3268, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee2, 3274, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee3, 3280, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee4, 3286, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee5, 3290, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee6, 3294, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee7, 3298, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee8, 3302, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ee9, 3308, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eea, 3314, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eeb, 3320, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eec, 3326, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eed, 3332, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eee, 3338, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1eef, 3344, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef0, 3350, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef1, 3356, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef2, 3362, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef3, 3366, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef4, 3370, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef5, 3374, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef6, 3378, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef7, 3382, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef8, 3386, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ef9, 3390, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f00, 3394, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f01, 3399, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f02, 3404, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f03, 3411, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f04, 3418, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f05, 3425, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f06, 3432, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f07, 3439, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f08, 3446, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f09, 3451, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f0a, 3456, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f0b, 3463, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f0c, 3470, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f0d, 3477, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f0e, 3484, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f0f, 3491, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f10, 3498, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f11, 3503, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f12, 3508, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f13, 3515, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f14, 3522, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f15, 3529, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f18, 3536, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f19, 3541, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f1a, 3546, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f1b, 3553, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f1c, 3560, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f1d, 3567, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f20, 3574, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f21, 3579, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f22, 3584, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f23, 3591, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f24, 3598, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f25, 3605, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f26, 3612, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f27, 3619, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f28, 3626, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f29, 3631, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f2a, 3636, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f2b, 3643, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f2c, 3650, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f2d, 3657, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f2e, 3664, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f2f, 3671, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f30, 3678, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f31, 3683, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f32, 3688, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f33, 3695, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f34, 3702, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f35, 3709, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f36, 3716, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f37, 3723, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f38, 3730, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f39, 3735, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f3a, 3740, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f3b, 3747, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f3c, 3754, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f3d, 3761, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f3e, 3768, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f3f, 3775, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f40, 3782, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f41, 3787, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f42, 3792, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f43, 3799, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f44, 3806, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f45, 3813, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f48, 3820, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f49, 3825, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f4a, 3830, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f4b, 3837, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f4c, 3844, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f4d, 3851, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f50, 3858, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f51, 3863, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f52, 3868, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f53, 3875, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f54, 3882, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f55, 3889, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f56, 3896, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f57, 3903, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f59, 3910, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f5b, 3915, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f5d, 3922, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f5f, 3929, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f60, 3936, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f61, 3941, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f62, 3946, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f63, 3953, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f64, 3960, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f65, 3967, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f66, 3974, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f67, 3981, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f68, 3988, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f69, 3993, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f6a, 3998, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f6b, 4005, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f6c, 4012, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f6d, 4019, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f6e, 4026, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f6f, 4033, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f70, 4040, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f71, 1316, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f72, 4045, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f73, 1321, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f74, 4050, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f75, 1326, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f76, 4055, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f77, 1331, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f78, 4060, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f79, 1353, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f7a, 4065, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f7b, 1358, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f7c, 4070, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f7d, 1363, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f80, 4075, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f81, 4082, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f82, 4089, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f83, 4098, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f84, 4107, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f85, 4116, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f86, 4125, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f87, 4134, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f88, 4143, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f89, 4150, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f8a, 4157, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f8b, 4166, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f8c, 4175, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f8d, 4184, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f8e, 4193, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f8f, 4202, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f90, 4211, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f91, 4218, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f92, 4225, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f93, 4234, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f94, 4243, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f95, 4252, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f96, 4261, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f97, 4270, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f98, 4279, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f99, 4286, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f9a, 4293, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f9b, 4302, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f9c, 4311, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f9d, 4320, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f9e, 4329, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1f9f, 4338, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa0, 4347, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa1, 4354, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa2, 4361, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa3, 4370, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa4, 4379, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa5, 4388, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa6, 4397, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa7, 4406, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa8, 4415, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fa9, 4422, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1faa, 4429, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fab, 4438, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fac, 4447, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fad, 4456, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fae, 4465, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1faf, 4474, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb0, 4483, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb1, 4488, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb2, 4493, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb3, 4500, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb4, 4505, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb6, 4512, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb7, 4517, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb8, 4524, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fb9, 4529, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fba, 4534, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fbb, 1261, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fbc, 4539, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fbd, G_UNICODE_NOT_PRESENT_OFFSET, 4544 },
+  { 0x1fbe, 4548, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fbf, G_UNICODE_NOT_PRESENT_OFFSET, 4544 },
+  { 0x1fc0, G_UNICODE_NOT_PRESENT_OFFSET, 4551 },
+  { 0x1fc1, 4555, 4560 },
+  { 0x1fc2, 4566, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fc3, 4573, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fc4, 4578, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fc6, 4585, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fc7, 4590, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fc8, 4597, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fc9, 1269, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fca, 4602, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fcb, 1274, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fcc, 4607, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fcd, 4612, 4618 },
+  { 0x1fce, 4624, 4630 },
+  { 0x1fcf, 4636, 4642 },
+  { 0x1fd0, 4648, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fd1, 4653, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fd2, 4658, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fd3, 1299, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fd6, 4665, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fd7, 4670, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fd8, 4677, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fd9, 4682, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fda, 4687, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fdb, 1279, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fdd, 4692, 4698 },
+  { 0x1fde, 4704, 4710 },
+  { 0x1fdf, 4716, 4722 },
+  { 0x1fe0, 4728, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe1, 4733, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe2, 4738, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe3, 1336, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe4, 4745, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe5, 4750, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe6, 4755, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe7, 4760, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe8, 4767, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fe9, 4772, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fea, 4777, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1feb, 1289, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fec, 4782, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1fed, 4787, 4792 },
+  { 0x1fee, 1250, 1255 },
+  { 0x1fef, 4798, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ff2, 4800, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ff3, 4807, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ff4, 4812, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ff6, 4819, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ff7, 4824, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ff8, 4831, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ff9, 1284, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ffa, 4836, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ffb, 1294, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ffc, 4841, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1ffd, 4846, 16 },
+  { 0x1ffe, G_UNICODE_NOT_PRESENT_OFFSET, 4849 },
+  { 0x2000, 4853, 0 },
+  { 0x2001, 4857, 0 },
+  { 0x2002, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2003, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2004, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2005, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2006, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2007, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2008, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2009, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x200a, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2011, G_UNICODE_NOT_PRESENT_OFFSET, 4861 },
+  { 0x2017, G_UNICODE_NOT_PRESENT_OFFSET, 4865 },
+  { 0x2024, G_UNICODE_NOT_PRESENT_OFFSET, 4869 },
+  { 0x2025, G_UNICODE_NOT_PRESENT_OFFSET, 4871 },
+  { 0x2026, G_UNICODE_NOT_PRESENT_OFFSET, 4874 },
+  { 0x202f, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2033, G_UNICODE_NOT_PRESENT_OFFSET, 4878 },
+  { 0x2034, G_UNICODE_NOT_PRESENT_OFFSET, 4885 },
+  { 0x2036, G_UNICODE_NOT_PRESENT_OFFSET, 4895 },
+  { 0x2037, G_UNICODE_NOT_PRESENT_OFFSET, 4902 },
+  { 0x203c, G_UNICODE_NOT_PRESENT_OFFSET, 4912 },
+  { 0x203e, G_UNICODE_NOT_PRESENT_OFFSET, 4915 },
+  { 0x2047, G_UNICODE_NOT_PRESENT_OFFSET, 4919 },
+  { 0x2048, G_UNICODE_NOT_PRESENT_OFFSET, 4922 },
+  { 0x2049, G_UNICODE_NOT_PRESENT_OFFSET, 4925 },
+  { 0x2057, G_UNICODE_NOT_PRESENT_OFFSET, 4928 },
+  { 0x205f, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x2070, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x2071, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x2074, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x2075, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x2076, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x2077, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x2078, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x2079, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x207a, G_UNICODE_NOT_PRESENT_OFFSET, 4957 },
+  { 0x207b, G_UNICODE_NOT_PRESENT_OFFSET, 4959 },
+  { 0x207c, G_UNICODE_NOT_PRESENT_OFFSET, 4963 },
+  { 0x207d, G_UNICODE_NOT_PRESENT_OFFSET, 4965 },
+  { 0x207e, G_UNICODE_NOT_PRESENT_OFFSET, 4967 },
+  { 0x207f, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x2080, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x2081, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x2082, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x2083, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x2084, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x2085, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x2086, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x2087, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x2088, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x2089, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x208a, G_UNICODE_NOT_PRESENT_OFFSET, 4957 },
+  { 0x208b, G_UNICODE_NOT_PRESENT_OFFSET, 4959 },
+  { 0x208c, G_UNICODE_NOT_PRESENT_OFFSET, 4963 },
+  { 0x208d, G_UNICODE_NOT_PRESENT_OFFSET, 4965 },
+  { 0x208e, G_UNICODE_NOT_PRESENT_OFFSET, 4967 },
+  { 0x20a8, G_UNICODE_NOT_PRESENT_OFFSET, 4971 },
+  { 0x2100, G_UNICODE_NOT_PRESENT_OFFSET, 4974 },
+  { 0x2101, G_UNICODE_NOT_PRESENT_OFFSET, 4978 },
+  { 0x2102, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x2103, G_UNICODE_NOT_PRESENT_OFFSET, 4984 },
+  { 0x2105, G_UNICODE_NOT_PRESENT_OFFSET, 4988 },
+  { 0x2106, G_UNICODE_NOT_PRESENT_OFFSET, 4992 },
+  { 0x2107, G_UNICODE_NOT_PRESENT_OFFSET, 4996 },
+  { 0x2109, G_UNICODE_NOT_PRESENT_OFFSET, 4999 },
+  { 0x210a, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x210b, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x210c, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x210d, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x210e, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x210f, G_UNICODE_NOT_PRESENT_OFFSET, 5007 },
+  { 0x2110, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x2111, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x2112, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x2113, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x2115, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x2116, G_UNICODE_NOT_PRESENT_OFFSET, 5016 },
+  { 0x2119, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x211a, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x211b, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x211c, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x211d, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x2120, G_UNICODE_NOT_PRESENT_OFFSET, 5025 },
+  { 0x2121, G_UNICODE_NOT_PRESENT_OFFSET, 5028 },
+  { 0x2122, G_UNICODE_NOT_PRESENT_OFFSET, 5032 },
+  { 0x2124, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x2126, 5037, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2128, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x212a, 5040, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x212b, 69, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x212c, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x212d, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x212f, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x2130, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x2131, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x2133, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x2134, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x2135, G_UNICODE_NOT_PRESENT_OFFSET, 5052 },
+  { 0x2136, G_UNICODE_NOT_PRESENT_OFFSET, 5055 },
+  { 0x2137, G_UNICODE_NOT_PRESENT_OFFSET, 5058 },
+  { 0x2138, G_UNICODE_NOT_PRESENT_OFFSET, 5061 },
+  { 0x2139, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x213d, G_UNICODE_NOT_PRESENT_OFFSET, 5064 },
+  { 0x213e, G_UNICODE_NOT_PRESENT_OFFSET, 5067 },
+  { 0x213f, G_UNICODE_NOT_PRESENT_OFFSET, 5070 },
+  { 0x2140, G_UNICODE_NOT_PRESENT_OFFSET, 5073 },
+  { 0x2145, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x2146, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x2147, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x2148, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x2149, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x2153, G_UNICODE_NOT_PRESENT_OFFSET, 5081 },
+  { 0x2154, G_UNICODE_NOT_PRESENT_OFFSET, 5087 },
+  { 0x2155, G_UNICODE_NOT_PRESENT_OFFSET, 5093 },
+  { 0x2156, G_UNICODE_NOT_PRESENT_OFFSET, 5099 },
+  { 0x2157, G_UNICODE_NOT_PRESENT_OFFSET, 5105 },
+  { 0x2158, G_UNICODE_NOT_PRESENT_OFFSET, 5111 },
+  { 0x2159, G_UNICODE_NOT_PRESENT_OFFSET, 5117 },
+  { 0x215a, G_UNICODE_NOT_PRESENT_OFFSET, 5123 },
+  { 0x215b, G_UNICODE_NOT_PRESENT_OFFSET, 5129 },
+  { 0x215c, G_UNICODE_NOT_PRESENT_OFFSET, 5135 },
+  { 0x215d, G_UNICODE_NOT_PRESENT_OFFSET, 5141 },
+  { 0x215e, G_UNICODE_NOT_PRESENT_OFFSET, 5147 },
+  { 0x215f, G_UNICODE_NOT_PRESENT_OFFSET, 5153 },
+  { 0x2160, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x2161, G_UNICODE_NOT_PRESENT_OFFSET, 5158 },
+  { 0x2162, G_UNICODE_NOT_PRESENT_OFFSET, 5161 },
+  { 0x2163, G_UNICODE_NOT_PRESENT_OFFSET, 5165 },
+  { 0x2164, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x2165, G_UNICODE_NOT_PRESENT_OFFSET, 5170 },
+  { 0x2166, G_UNICODE_NOT_PRESENT_OFFSET, 5173 },
+  { 0x2167, G_UNICODE_NOT_PRESENT_OFFSET, 5177 },
+  { 0x2168, G_UNICODE_NOT_PRESENT_OFFSET, 5182 },
+  { 0x2169, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x216a, G_UNICODE_NOT_PRESENT_OFFSET, 5187 },
+  { 0x216b, G_UNICODE_NOT_PRESENT_OFFSET, 5190 },
+  { 0x216c, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x216d, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x216e, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x216f, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x2170, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x2171, G_UNICODE_NOT_PRESENT_OFFSET, 5194 },
+  { 0x2172, G_UNICODE_NOT_PRESENT_OFFSET, 5197 },
+  { 0x2173, G_UNICODE_NOT_PRESENT_OFFSET, 5201 },
+  { 0x2174, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x2175, G_UNICODE_NOT_PRESENT_OFFSET, 5206 },
+  { 0x2176, G_UNICODE_NOT_PRESENT_OFFSET, 5209 },
+  { 0x2177, G_UNICODE_NOT_PRESENT_OFFSET, 5213 },
+  { 0x2178, G_UNICODE_NOT_PRESENT_OFFSET, 5218 },
+  { 0x2179, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x217a, G_UNICODE_NOT_PRESENT_OFFSET, 5221 },
+  { 0x217b, G_UNICODE_NOT_PRESENT_OFFSET, 5224 },
+  { 0x217c, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x217d, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x217e, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x217f, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x219a, 5232, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x219b, 5238, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x21ae, 5244, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x21cd, 5250, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x21ce, 5256, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x21cf, 5262, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2204, 5268, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2209, 5274, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x220c, 5280, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2224, 5286, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2226, 5292, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x222c, G_UNICODE_NOT_PRESENT_OFFSET, 5298 },
+  { 0x222d, G_UNICODE_NOT_PRESENT_OFFSET, 5305 },
+  { 0x222f, G_UNICODE_NOT_PRESENT_OFFSET, 5315 },
+  { 0x2230, G_UNICODE_NOT_PRESENT_OFFSET, 5322 },
+  { 0x2241, 5332, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2244, 5338, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2247, 5344, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2249, 5350, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2260, 5356, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2262, 5360, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x226d, 5366, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x226e, 5372, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x226f, 5376, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2270, 5380, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2271, 5386, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2274, 5392, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2275, 5398, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2278, 5404, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2279, 5410, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2280, 5416, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2281, 5422, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2284, 5428, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2285, 5434, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2288, 5440, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2289, 5446, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22ac, 5452, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22ad, 5458, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22ae, 5464, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22af, 5470, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22e0, 5476, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22e1, 5482, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22e2, 5488, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22e3, 5494, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22ea, 5500, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22eb, 5506, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22ec, 5512, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x22ed, 5518, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2329, 5524, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x232a, 5528, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2460, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x2461, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x2462, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x2463, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x2464, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x2465, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x2466, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x2467, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x2468, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x2469, G_UNICODE_NOT_PRESENT_OFFSET, 5532 },
+  { 0x246a, G_UNICODE_NOT_PRESENT_OFFSET, 5535 },
+  { 0x246b, G_UNICODE_NOT_PRESENT_OFFSET, 5538 },
+  { 0x246c, G_UNICODE_NOT_PRESENT_OFFSET, 5541 },
+  { 0x246d, G_UNICODE_NOT_PRESENT_OFFSET, 5544 },
+  { 0x246e, G_UNICODE_NOT_PRESENT_OFFSET, 5547 },
+  { 0x246f, G_UNICODE_NOT_PRESENT_OFFSET, 5550 },
+  { 0x2470, G_UNICODE_NOT_PRESENT_OFFSET, 5553 },
+  { 0x2471, G_UNICODE_NOT_PRESENT_OFFSET, 5556 },
+  { 0x2472, G_UNICODE_NOT_PRESENT_OFFSET, 5559 },
+  { 0x2473, G_UNICODE_NOT_PRESENT_OFFSET, 5562 },
+  { 0x2474, G_UNICODE_NOT_PRESENT_OFFSET, 5565 },
+  { 0x2475, G_UNICODE_NOT_PRESENT_OFFSET, 5569 },
+  { 0x2476, G_UNICODE_NOT_PRESENT_OFFSET, 5573 },
+  { 0x2477, G_UNICODE_NOT_PRESENT_OFFSET, 5577 },
+  { 0x2478, G_UNICODE_NOT_PRESENT_OFFSET, 5581 },
+  { 0x2479, G_UNICODE_NOT_PRESENT_OFFSET, 5585 },
+  { 0x247a, G_UNICODE_NOT_PRESENT_OFFSET, 5589 },
+  { 0x247b, G_UNICODE_NOT_PRESENT_OFFSET, 5593 },
+  { 0x247c, G_UNICODE_NOT_PRESENT_OFFSET, 5597 },
+  { 0x247d, G_UNICODE_NOT_PRESENT_OFFSET, 5601 },
+  { 0x247e, G_UNICODE_NOT_PRESENT_OFFSET, 5606 },
+  { 0x247f, G_UNICODE_NOT_PRESENT_OFFSET, 5611 },
+  { 0x2480, G_UNICODE_NOT_PRESENT_OFFSET, 5616 },
+  { 0x2481, G_UNICODE_NOT_PRESENT_OFFSET, 5621 },
+  { 0x2482, G_UNICODE_NOT_PRESENT_OFFSET, 5626 },
+  { 0x2483, G_UNICODE_NOT_PRESENT_OFFSET, 5631 },
+  { 0x2484, G_UNICODE_NOT_PRESENT_OFFSET, 5636 },
+  { 0x2485, G_UNICODE_NOT_PRESENT_OFFSET, 5641 },
+  { 0x2486, G_UNICODE_NOT_PRESENT_OFFSET, 5646 },
+  { 0x2487, G_UNICODE_NOT_PRESENT_OFFSET, 5651 },
+  { 0x2488, G_UNICODE_NOT_PRESENT_OFFSET, 5656 },
+  { 0x2489, G_UNICODE_NOT_PRESENT_OFFSET, 5659 },
+  { 0x248a, G_UNICODE_NOT_PRESENT_OFFSET, 5662 },
+  { 0x248b, G_UNICODE_NOT_PRESENT_OFFSET, 5665 },
+  { 0x248c, G_UNICODE_NOT_PRESENT_OFFSET, 5668 },
+  { 0x248d, G_UNICODE_NOT_PRESENT_OFFSET, 5671 },
+  { 0x248e, G_UNICODE_NOT_PRESENT_OFFSET, 5674 },
+  { 0x248f, G_UNICODE_NOT_PRESENT_OFFSET, 5677 },
+  { 0x2490, G_UNICODE_NOT_PRESENT_OFFSET, 5680 },
+  { 0x2491, G_UNICODE_NOT_PRESENT_OFFSET, 5683 },
+  { 0x2492, G_UNICODE_NOT_PRESENT_OFFSET, 5687 },
+  { 0x2493, G_UNICODE_NOT_PRESENT_OFFSET, 5691 },
+  { 0x2494, G_UNICODE_NOT_PRESENT_OFFSET, 5695 },
+  { 0x2495, G_UNICODE_NOT_PRESENT_OFFSET, 5699 },
+  { 0x2496, G_UNICODE_NOT_PRESENT_OFFSET, 5703 },
+  { 0x2497, G_UNICODE_NOT_PRESENT_OFFSET, 5707 },
+  { 0x2498, G_UNICODE_NOT_PRESENT_OFFSET, 5711 },
+  { 0x2499, G_UNICODE_NOT_PRESENT_OFFSET, 5715 },
+  { 0x249a, G_UNICODE_NOT_PRESENT_OFFSET, 5719 },
+  { 0x249b, G_UNICODE_NOT_PRESENT_OFFSET, 5723 },
+  { 0x249c, G_UNICODE_NOT_PRESENT_OFFSET, 5727 },
+  { 0x249d, G_UNICODE_NOT_PRESENT_OFFSET, 5731 },
+  { 0x249e, G_UNICODE_NOT_PRESENT_OFFSET, 5735 },
+  { 0x249f, G_UNICODE_NOT_PRESENT_OFFSET, 5739 },
+  { 0x24a0, G_UNICODE_NOT_PRESENT_OFFSET, 5743 },
+  { 0x24a1, G_UNICODE_NOT_PRESENT_OFFSET, 5747 },
+  { 0x24a2, G_UNICODE_NOT_PRESENT_OFFSET, 5751 },
+  { 0x24a3, G_UNICODE_NOT_PRESENT_OFFSET, 5755 },
+  { 0x24a4, G_UNICODE_NOT_PRESENT_OFFSET, 5759 },
+  { 0x24a5, G_UNICODE_NOT_PRESENT_OFFSET, 5763 },
+  { 0x24a6, G_UNICODE_NOT_PRESENT_OFFSET, 5767 },
+  { 0x24a7, G_UNICODE_NOT_PRESENT_OFFSET, 5771 },
+  { 0x24a8, G_UNICODE_NOT_PRESENT_OFFSET, 5775 },
+  { 0x24a9, G_UNICODE_NOT_PRESENT_OFFSET, 5779 },
+  { 0x24aa, G_UNICODE_NOT_PRESENT_OFFSET, 5783 },
+  { 0x24ab, G_UNICODE_NOT_PRESENT_OFFSET, 5787 },
+  { 0x24ac, G_UNICODE_NOT_PRESENT_OFFSET, 5791 },
+  { 0x24ad, G_UNICODE_NOT_PRESENT_OFFSET, 5795 },
+  { 0x24ae, G_UNICODE_NOT_PRESENT_OFFSET, 5799 },
+  { 0x24af, G_UNICODE_NOT_PRESENT_OFFSET, 5803 },
+  { 0x24b0, G_UNICODE_NOT_PRESENT_OFFSET, 5807 },
+  { 0x24b1, G_UNICODE_NOT_PRESENT_OFFSET, 5811 },
+  { 0x24b2, G_UNICODE_NOT_PRESENT_OFFSET, 5815 },
+  { 0x24b3, G_UNICODE_NOT_PRESENT_OFFSET, 5819 },
+  { 0x24b4, G_UNICODE_NOT_PRESENT_OFFSET, 5823 },
+  { 0x24b5, G_UNICODE_NOT_PRESENT_OFFSET, 5827 },
+  { 0x24b6, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x24b7, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x24b8, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x24b9, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x24ba, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x24bb, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x24bc, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x24bd, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x24be, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x24bf, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x24c0, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x24c1, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x24c2, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x24c3, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x24c4, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x24c5, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x24c6, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x24c7, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x24c8, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x24c9, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x24ca, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x24cb, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x24cc, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x24cd, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x24ce, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x24cf, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x24d0, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x24d1, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x24d2, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x24d3, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x24d4, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x24d5, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x24d6, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x24d7, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x24d8, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x24d9, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x24da, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x24db, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x24dc, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x24dd, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x24de, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x24df, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x24e0, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x24e1, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x24e2, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x24e3, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x24e4, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x24e5, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x24e6, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x24e7, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x24e8, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x24e9, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x24ea, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x2a0c, G_UNICODE_NOT_PRESENT_OFFSET, 5865 },
+  { 0x2a74, G_UNICODE_NOT_PRESENT_OFFSET, 5878 },
+  { 0x2a75, G_UNICODE_NOT_PRESENT_OFFSET, 5882 },
+  { 0x2a76, G_UNICODE_NOT_PRESENT_OFFSET, 5885 },
+  { 0x2adc, 5889, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2e9f, G_UNICODE_NOT_PRESENT_OFFSET, 5895 },
+  { 0x2ef3, G_UNICODE_NOT_PRESENT_OFFSET, 5899 },
+  { 0x2f00, G_UNICODE_NOT_PRESENT_OFFSET, 5903 },
+  { 0x2f01, G_UNICODE_NOT_PRESENT_OFFSET, 5907 },
+  { 0x2f02, G_UNICODE_NOT_PRESENT_OFFSET, 5911 },
+  { 0x2f03, G_UNICODE_NOT_PRESENT_OFFSET, 5915 },
+  { 0x2f04, G_UNICODE_NOT_PRESENT_OFFSET, 5919 },
+  { 0x2f05, G_UNICODE_NOT_PRESENT_OFFSET, 5923 },
+  { 0x2f06, G_UNICODE_NOT_PRESENT_OFFSET, 5927 },
+  { 0x2f07, G_UNICODE_NOT_PRESENT_OFFSET, 5931 },
+  { 0x2f08, G_UNICODE_NOT_PRESENT_OFFSET, 5935 },
+  { 0x2f09, G_UNICODE_NOT_PRESENT_OFFSET, 5939 },
+  { 0x2f0a, G_UNICODE_NOT_PRESENT_OFFSET, 5943 },
+  { 0x2f0b, G_UNICODE_NOT_PRESENT_OFFSET, 5947 },
+  { 0x2f0c, G_UNICODE_NOT_PRESENT_OFFSET, 5951 },
+  { 0x2f0d, G_UNICODE_NOT_PRESENT_OFFSET, 5955 },
+  { 0x2f0e, G_UNICODE_NOT_PRESENT_OFFSET, 5959 },
+  { 0x2f0f, G_UNICODE_NOT_PRESENT_OFFSET, 5963 },
+  { 0x2f10, G_UNICODE_NOT_PRESENT_OFFSET, 5967 },
+  { 0x2f11, G_UNICODE_NOT_PRESENT_OFFSET, 5971 },
+  { 0x2f12, G_UNICODE_NOT_PRESENT_OFFSET, 5975 },
+  { 0x2f13, G_UNICODE_NOT_PRESENT_OFFSET, 5979 },
+  { 0x2f14, G_UNICODE_NOT_PRESENT_OFFSET, 5983 },
+  { 0x2f15, G_UNICODE_NOT_PRESENT_OFFSET, 5987 },
+  { 0x2f16, G_UNICODE_NOT_PRESENT_OFFSET, 5991 },
+  { 0x2f17, G_UNICODE_NOT_PRESENT_OFFSET, 5995 },
+  { 0x2f18, G_UNICODE_NOT_PRESENT_OFFSET, 5999 },
+  { 0x2f19, G_UNICODE_NOT_PRESENT_OFFSET, 6003 },
+  { 0x2f1a, G_UNICODE_NOT_PRESENT_OFFSET, 6007 },
+  { 0x2f1b, G_UNICODE_NOT_PRESENT_OFFSET, 6011 },
+  { 0x2f1c, G_UNICODE_NOT_PRESENT_OFFSET, 6015 },
+  { 0x2f1d, G_UNICODE_NOT_PRESENT_OFFSET, 6019 },
+  { 0x2f1e, G_UNICODE_NOT_PRESENT_OFFSET, 6023 },
+  { 0x2f1f, G_UNICODE_NOT_PRESENT_OFFSET, 6027 },
+  { 0x2f20, G_UNICODE_NOT_PRESENT_OFFSET, 6031 },
+  { 0x2f21, G_UNICODE_NOT_PRESENT_OFFSET, 6035 },
+  { 0x2f22, G_UNICODE_NOT_PRESENT_OFFSET, 6039 },
+  { 0x2f23, G_UNICODE_NOT_PRESENT_OFFSET, 6043 },
+  { 0x2f24, G_UNICODE_NOT_PRESENT_OFFSET, 6047 },
+  { 0x2f25, G_UNICODE_NOT_PRESENT_OFFSET, 6051 },
+  { 0x2f26, G_UNICODE_NOT_PRESENT_OFFSET, 6055 },
+  { 0x2f27, G_UNICODE_NOT_PRESENT_OFFSET, 6059 },
+  { 0x2f28, G_UNICODE_NOT_PRESENT_OFFSET, 6063 },
+  { 0x2f29, G_UNICODE_NOT_PRESENT_OFFSET, 6067 },
+  { 0x2f2a, G_UNICODE_NOT_PRESENT_OFFSET, 6071 },
+  { 0x2f2b, G_UNICODE_NOT_PRESENT_OFFSET, 6075 },
+  { 0x2f2c, G_UNICODE_NOT_PRESENT_OFFSET, 6079 },
+  { 0x2f2d, G_UNICODE_NOT_PRESENT_OFFSET, 6083 },
+  { 0x2f2e, G_UNICODE_NOT_PRESENT_OFFSET, 6087 },
+  { 0x2f2f, G_UNICODE_NOT_PRESENT_OFFSET, 6091 },
+  { 0x2f30, G_UNICODE_NOT_PRESENT_OFFSET, 6095 },
+  { 0x2f31, G_UNICODE_NOT_PRESENT_OFFSET, 6099 },
+  { 0x2f32, G_UNICODE_NOT_PRESENT_OFFSET, 6103 },
+  { 0x2f33, G_UNICODE_NOT_PRESENT_OFFSET, 6107 },
+  { 0x2f34, G_UNICODE_NOT_PRESENT_OFFSET, 6111 },
+  { 0x2f35, G_UNICODE_NOT_PRESENT_OFFSET, 6115 },
+  { 0x2f36, G_UNICODE_NOT_PRESENT_OFFSET, 6119 },
+  { 0x2f37, G_UNICODE_NOT_PRESENT_OFFSET, 6123 },
+  { 0x2f38, G_UNICODE_NOT_PRESENT_OFFSET, 6127 },
+  { 0x2f39, G_UNICODE_NOT_PRESENT_OFFSET, 6131 },
+  { 0x2f3a, G_UNICODE_NOT_PRESENT_OFFSET, 6135 },
+  { 0x2f3b, G_UNICODE_NOT_PRESENT_OFFSET, 6139 },
+  { 0x2f3c, G_UNICODE_NOT_PRESENT_OFFSET, 6143 },
+  { 0x2f3d, G_UNICODE_NOT_PRESENT_OFFSET, 6147 },
+  { 0x2f3e, G_UNICODE_NOT_PRESENT_OFFSET, 6151 },
+  { 0x2f3f, G_UNICODE_NOT_PRESENT_OFFSET, 6155 },
+  { 0x2f40, G_UNICODE_NOT_PRESENT_OFFSET, 6159 },
+  { 0x2f41, G_UNICODE_NOT_PRESENT_OFFSET, 6163 },
+  { 0x2f42, G_UNICODE_NOT_PRESENT_OFFSET, 6167 },
+  { 0x2f43, G_UNICODE_NOT_PRESENT_OFFSET, 6171 },
+  { 0x2f44, G_UNICODE_NOT_PRESENT_OFFSET, 6175 },
+  { 0x2f45, G_UNICODE_NOT_PRESENT_OFFSET, 6179 },
+  { 0x2f46, G_UNICODE_NOT_PRESENT_OFFSET, 6183 },
+  { 0x2f47, G_UNICODE_NOT_PRESENT_OFFSET, 6187 },
+  { 0x2f48, G_UNICODE_NOT_PRESENT_OFFSET, 6191 },
+  { 0x2f49, G_UNICODE_NOT_PRESENT_OFFSET, 6195 },
+  { 0x2f4a, G_UNICODE_NOT_PRESENT_OFFSET, 6199 },
+  { 0x2f4b, G_UNICODE_NOT_PRESENT_OFFSET, 6203 },
+  { 0x2f4c, G_UNICODE_NOT_PRESENT_OFFSET, 6207 },
+  { 0x2f4d, G_UNICODE_NOT_PRESENT_OFFSET, 6211 },
+  { 0x2f4e, G_UNICODE_NOT_PRESENT_OFFSET, 6215 },
+  { 0x2f4f, G_UNICODE_NOT_PRESENT_OFFSET, 6219 },
+  { 0x2f50, G_UNICODE_NOT_PRESENT_OFFSET, 6223 },
+  { 0x2f51, G_UNICODE_NOT_PRESENT_OFFSET, 6227 },
+  { 0x2f52, G_UNICODE_NOT_PRESENT_OFFSET, 6231 },
+  { 0x2f53, G_UNICODE_NOT_PRESENT_OFFSET, 6235 },
+  { 0x2f54, G_UNICODE_NOT_PRESENT_OFFSET, 6239 },
+  { 0x2f55, G_UNICODE_NOT_PRESENT_OFFSET, 6243 },
+  { 0x2f56, G_UNICODE_NOT_PRESENT_OFFSET, 6247 },
+  { 0x2f57, G_UNICODE_NOT_PRESENT_OFFSET, 6251 },
+  { 0x2f58, G_UNICODE_NOT_PRESENT_OFFSET, 6255 },
+  { 0x2f59, G_UNICODE_NOT_PRESENT_OFFSET, 6259 },
+  { 0x2f5a, G_UNICODE_NOT_PRESENT_OFFSET, 6263 },
+  { 0x2f5b, G_UNICODE_NOT_PRESENT_OFFSET, 6267 },
+  { 0x2f5c, G_UNICODE_NOT_PRESENT_OFFSET, 6271 },
+  { 0x2f5d, G_UNICODE_NOT_PRESENT_OFFSET, 6275 },
+  { 0x2f5e, G_UNICODE_NOT_PRESENT_OFFSET, 6279 },
+  { 0x2f5f, G_UNICODE_NOT_PRESENT_OFFSET, 6283 },
+  { 0x2f60, G_UNICODE_NOT_PRESENT_OFFSET, 6287 },
+  { 0x2f61, G_UNICODE_NOT_PRESENT_OFFSET, 6291 },
+  { 0x2f62, G_UNICODE_NOT_PRESENT_OFFSET, 6295 },
+  { 0x2f63, G_UNICODE_NOT_PRESENT_OFFSET, 6299 },
+  { 0x2f64, G_UNICODE_NOT_PRESENT_OFFSET, 6303 },
+  { 0x2f65, G_UNICODE_NOT_PRESENT_OFFSET, 6307 },
+  { 0x2f66, G_UNICODE_NOT_PRESENT_OFFSET, 6311 },
+  { 0x2f67, G_UNICODE_NOT_PRESENT_OFFSET, 6315 },
+  { 0x2f68, G_UNICODE_NOT_PRESENT_OFFSET, 6319 },
+  { 0x2f69, G_UNICODE_NOT_PRESENT_OFFSET, 6323 },
+  { 0x2f6a, G_UNICODE_NOT_PRESENT_OFFSET, 6327 },
+  { 0x2f6b, G_UNICODE_NOT_PRESENT_OFFSET, 6331 },
+  { 0x2f6c, G_UNICODE_NOT_PRESENT_OFFSET, 6335 },
+  { 0x2f6d, G_UNICODE_NOT_PRESENT_OFFSET, 6339 },
+  { 0x2f6e, G_UNICODE_NOT_PRESENT_OFFSET, 6343 },
+  { 0x2f6f, G_UNICODE_NOT_PRESENT_OFFSET, 6347 },
+  { 0x2f70, G_UNICODE_NOT_PRESENT_OFFSET, 6351 },
+  { 0x2f71, G_UNICODE_NOT_PRESENT_OFFSET, 6355 },
+  { 0x2f72, G_UNICODE_NOT_PRESENT_OFFSET, 6359 },
+  { 0x2f73, G_UNICODE_NOT_PRESENT_OFFSET, 6363 },
+  { 0x2f74, G_UNICODE_NOT_PRESENT_OFFSET, 6367 },
+  { 0x2f75, G_UNICODE_NOT_PRESENT_OFFSET, 6371 },
+  { 0x2f76, G_UNICODE_NOT_PRESENT_OFFSET, 6375 },
+  { 0x2f77, G_UNICODE_NOT_PRESENT_OFFSET, 6379 },
+  { 0x2f78, G_UNICODE_NOT_PRESENT_OFFSET, 6383 },
+  { 0x2f79, G_UNICODE_NOT_PRESENT_OFFSET, 6387 },
+  { 0x2f7a, G_UNICODE_NOT_PRESENT_OFFSET, 6391 },
+  { 0x2f7b, G_UNICODE_NOT_PRESENT_OFFSET, 6395 },
+  { 0x2f7c, G_UNICODE_NOT_PRESENT_OFFSET, 6399 },
+  { 0x2f7d, G_UNICODE_NOT_PRESENT_OFFSET, 6403 },
+  { 0x2f7e, G_UNICODE_NOT_PRESENT_OFFSET, 6407 },
+  { 0x2f7f, G_UNICODE_NOT_PRESENT_OFFSET, 6411 },
+  { 0x2f80, G_UNICODE_NOT_PRESENT_OFFSET, 6415 },
+  { 0x2f81, G_UNICODE_NOT_PRESENT_OFFSET, 6419 },
+  { 0x2f82, G_UNICODE_NOT_PRESENT_OFFSET, 6423 },
+  { 0x2f83, G_UNICODE_NOT_PRESENT_OFFSET, 6427 },
+  { 0x2f84, G_UNICODE_NOT_PRESENT_OFFSET, 6431 },
+  { 0x2f85, G_UNICODE_NOT_PRESENT_OFFSET, 6435 },
+  { 0x2f86, G_UNICODE_NOT_PRESENT_OFFSET, 6439 },
+  { 0x2f87, G_UNICODE_NOT_PRESENT_OFFSET, 6443 },
+  { 0x2f88, G_UNICODE_NOT_PRESENT_OFFSET, 6447 },
+  { 0x2f89, G_UNICODE_NOT_PRESENT_OFFSET, 6451 },
+  { 0x2f8a, G_UNICODE_NOT_PRESENT_OFFSET, 6455 },
+  { 0x2f8b, G_UNICODE_NOT_PRESENT_OFFSET, 6459 },
+  { 0x2f8c, G_UNICODE_NOT_PRESENT_OFFSET, 6463 },
+  { 0x2f8d, G_UNICODE_NOT_PRESENT_OFFSET, 6467 },
+  { 0x2f8e, G_UNICODE_NOT_PRESENT_OFFSET, 6471 },
+  { 0x2f8f, G_UNICODE_NOT_PRESENT_OFFSET, 6475 },
+  { 0x2f90, G_UNICODE_NOT_PRESENT_OFFSET, 6479 },
+  { 0x2f91, G_UNICODE_NOT_PRESENT_OFFSET, 6483 },
+  { 0x2f92, G_UNICODE_NOT_PRESENT_OFFSET, 6487 },
+  { 0x2f93, G_UNICODE_NOT_PRESENT_OFFSET, 6491 },
+  { 0x2f94, G_UNICODE_NOT_PRESENT_OFFSET, 6495 },
+  { 0x2f95, G_UNICODE_NOT_PRESENT_OFFSET, 6499 },
+  { 0x2f96, G_UNICODE_NOT_PRESENT_OFFSET, 6503 },
+  { 0x2f97, G_UNICODE_NOT_PRESENT_OFFSET, 6507 },
+  { 0x2f98, G_UNICODE_NOT_PRESENT_OFFSET, 6511 },
+  { 0x2f99, G_UNICODE_NOT_PRESENT_OFFSET, 6515 },
+  { 0x2f9a, G_UNICODE_NOT_PRESENT_OFFSET, 6519 },
+  { 0x2f9b, G_UNICODE_NOT_PRESENT_OFFSET, 6523 },
+  { 0x2f9c, G_UNICODE_NOT_PRESENT_OFFSET, 6527 },
+  { 0x2f9d, G_UNICODE_NOT_PRESENT_OFFSET, 6531 },
+  { 0x2f9e, G_UNICODE_NOT_PRESENT_OFFSET, 6535 },
+  { 0x2f9f, G_UNICODE_NOT_PRESENT_OFFSET, 6539 },
+  { 0x2fa0, G_UNICODE_NOT_PRESENT_OFFSET, 6543 },
+  { 0x2fa1, G_UNICODE_NOT_PRESENT_OFFSET, 6547 },
+  { 0x2fa2, G_UNICODE_NOT_PRESENT_OFFSET, 6551 },
+  { 0x2fa3, G_UNICODE_NOT_PRESENT_OFFSET, 6555 },
+  { 0x2fa4, G_UNICODE_NOT_PRESENT_OFFSET, 6559 },
+  { 0x2fa5, G_UNICODE_NOT_PRESENT_OFFSET, 6563 },
+  { 0x2fa6, G_UNICODE_NOT_PRESENT_OFFSET, 6567 },
+  { 0x2fa7, G_UNICODE_NOT_PRESENT_OFFSET, 6571 },
+  { 0x2fa8, G_UNICODE_NOT_PRESENT_OFFSET, 6575 },
+  { 0x2fa9, G_UNICODE_NOT_PRESENT_OFFSET, 6579 },
+  { 0x2faa, G_UNICODE_NOT_PRESENT_OFFSET, 6583 },
+  { 0x2fab, G_UNICODE_NOT_PRESENT_OFFSET, 6587 },
+  { 0x2fac, G_UNICODE_NOT_PRESENT_OFFSET, 6591 },
+  { 0x2fad, G_UNICODE_NOT_PRESENT_OFFSET, 6595 },
+  { 0x2fae, G_UNICODE_NOT_PRESENT_OFFSET, 6599 },
+  { 0x2faf, G_UNICODE_NOT_PRESENT_OFFSET, 6603 },
+  { 0x2fb0, G_UNICODE_NOT_PRESENT_OFFSET, 6607 },
+  { 0x2fb1, G_UNICODE_NOT_PRESENT_OFFSET, 6611 },
+  { 0x2fb2, G_UNICODE_NOT_PRESENT_OFFSET, 6615 },
+  { 0x2fb3, G_UNICODE_NOT_PRESENT_OFFSET, 6619 },
+  { 0x2fb4, G_UNICODE_NOT_PRESENT_OFFSET, 6623 },
+  { 0x2fb5, G_UNICODE_NOT_PRESENT_OFFSET, 6627 },
+  { 0x2fb6, G_UNICODE_NOT_PRESENT_OFFSET, 6631 },
+  { 0x2fb7, G_UNICODE_NOT_PRESENT_OFFSET, 6635 },
+  { 0x2fb8, G_UNICODE_NOT_PRESENT_OFFSET, 6639 },
+  { 0x2fb9, G_UNICODE_NOT_PRESENT_OFFSET, 6643 },
+  { 0x2fba, G_UNICODE_NOT_PRESENT_OFFSET, 6647 },
+  { 0x2fbb, G_UNICODE_NOT_PRESENT_OFFSET, 6651 },
+  { 0x2fbc, G_UNICODE_NOT_PRESENT_OFFSET, 6655 },
+  { 0x2fbd, G_UNICODE_NOT_PRESENT_OFFSET, 6659 },
+  { 0x2fbe, G_UNICODE_NOT_PRESENT_OFFSET, 6663 },
+  { 0x2fbf, G_UNICODE_NOT_PRESENT_OFFSET, 6667 },
+  { 0x2fc0, G_UNICODE_NOT_PRESENT_OFFSET, 6671 },
+  { 0x2fc1, G_UNICODE_NOT_PRESENT_OFFSET, 6675 },
+  { 0x2fc2, G_UNICODE_NOT_PRESENT_OFFSET, 6679 },
+  { 0x2fc3, G_UNICODE_NOT_PRESENT_OFFSET, 6683 },
+  { 0x2fc4, G_UNICODE_NOT_PRESENT_OFFSET, 6687 },
+  { 0x2fc5, G_UNICODE_NOT_PRESENT_OFFSET, 6691 },
+  { 0x2fc6, G_UNICODE_NOT_PRESENT_OFFSET, 6695 },
+  { 0x2fc7, G_UNICODE_NOT_PRESENT_OFFSET, 6699 },
+  { 0x2fc8, G_UNICODE_NOT_PRESENT_OFFSET, 6703 },
+  { 0x2fc9, G_UNICODE_NOT_PRESENT_OFFSET, 6707 },
+  { 0x2fca, G_UNICODE_NOT_PRESENT_OFFSET, 6711 },
+  { 0x2fcb, G_UNICODE_NOT_PRESENT_OFFSET, 6715 },
+  { 0x2fcc, G_UNICODE_NOT_PRESENT_OFFSET, 6719 },
+  { 0x2fcd, G_UNICODE_NOT_PRESENT_OFFSET, 6723 },
+  { 0x2fce, G_UNICODE_NOT_PRESENT_OFFSET, 6727 },
+  { 0x2fcf, G_UNICODE_NOT_PRESENT_OFFSET, 6731 },
+  { 0x2fd0, G_UNICODE_NOT_PRESENT_OFFSET, 6735 },
+  { 0x2fd1, G_UNICODE_NOT_PRESENT_OFFSET, 6739 },
+  { 0x2fd2, G_UNICODE_NOT_PRESENT_OFFSET, 6743 },
+  { 0x2fd3, G_UNICODE_NOT_PRESENT_OFFSET, 6747 },
+  { 0x2fd4, G_UNICODE_NOT_PRESENT_OFFSET, 6751 },
+  { 0x2fd5, G_UNICODE_NOT_PRESENT_OFFSET, 6755 },
+  { 0x3000, G_UNICODE_NOT_PRESENT_OFFSET, 0 },
+  { 0x3036, G_UNICODE_NOT_PRESENT_OFFSET, 6759 },
+  { 0x3038, G_UNICODE_NOT_PRESENT_OFFSET, 5995 },
+  { 0x3039, G_UNICODE_NOT_PRESENT_OFFSET, 6763 },
+  { 0x303a, G_UNICODE_NOT_PRESENT_OFFSET, 6767 },
+  { 0x304c, 6771, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x304e, 6778, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3050, 6785, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3052, 6792, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3054, 6799, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3056, 6806, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3058, 6813, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x305a, 6820, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x305c, 6827, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x305e, 6834, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3060, 6841, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3062, 6848, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3065, 6855, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3067, 6862, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3069, 6869, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3070, 6876, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3071, 6883, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3073, 6890, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3074, 6897, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3076, 6904, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3077, 6911, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3079, 6918, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x307a, 6925, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x307c, 6932, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x307d, 6939, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x3094, 6946, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x309b, G_UNICODE_NOT_PRESENT_OFFSET, 6953 },
+  { 0x309c, G_UNICODE_NOT_PRESENT_OFFSET, 6958 },
+  { 0x309e, 6963, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x309f, G_UNICODE_NOT_PRESENT_OFFSET, 6970 },
+  { 0x30ac, 6977, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30ae, 6984, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30b0, 6991, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30b2, 6998, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30b4, 7005, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30b6, 7012, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30b8, 7019, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30ba, 7026, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30bc, 7033, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30be, 7040, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30c0, 7047, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30c2, 7054, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30c5, 7061, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30c7, 7068, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30c9, 7075, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30d0, 7082, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30d1, 7089, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30d3, 7096, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30d4, 7103, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30d6, 7110, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30d7, 7117, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30d9, 7124, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30da, 7131, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30dc, 7138, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30dd, 7145, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30f4, 7152, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30f7, 7159, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30f8, 7166, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30f9, 7173, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30fa, 7180, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30fe, 7187, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x30ff, G_UNICODE_NOT_PRESENT_OFFSET, 7194 },
+  { 0x3131, G_UNICODE_NOT_PRESENT_OFFSET, 7201 },
+  { 0x3132, G_UNICODE_NOT_PRESENT_OFFSET, 7205 },
+  { 0x3133, G_UNICODE_NOT_PRESENT_OFFSET, 7209 },
+  { 0x3134, G_UNICODE_NOT_PRESENT_OFFSET, 7213 },
+  { 0x3135, G_UNICODE_NOT_PRESENT_OFFSET, 7217 },
+  { 0x3136, G_UNICODE_NOT_PRESENT_OFFSET, 7221 },
+  { 0x3137, G_UNICODE_NOT_PRESENT_OFFSET, 7225 },
+  { 0x3138, G_UNICODE_NOT_PRESENT_OFFSET, 7229 },
+  { 0x3139, G_UNICODE_NOT_PRESENT_OFFSET, 7233 },
+  { 0x313a, G_UNICODE_NOT_PRESENT_OFFSET, 7237 },
+  { 0x313b, G_UNICODE_NOT_PRESENT_OFFSET, 7241 },
+  { 0x313c, G_UNICODE_NOT_PRESENT_OFFSET, 7245 },
+  { 0x313d, G_UNICODE_NOT_PRESENT_OFFSET, 7249 },
+  { 0x313e, G_UNICODE_NOT_PRESENT_OFFSET, 7253 },
+  { 0x313f, G_UNICODE_NOT_PRESENT_OFFSET, 7257 },
+  { 0x3140, G_UNICODE_NOT_PRESENT_OFFSET, 7261 },
+  { 0x3141, G_UNICODE_NOT_PRESENT_OFFSET, 7265 },
+  { 0x3142, G_UNICODE_NOT_PRESENT_OFFSET, 7269 },
+  { 0x3143, G_UNICODE_NOT_PRESENT_OFFSET, 7273 },
+  { 0x3144, G_UNICODE_NOT_PRESENT_OFFSET, 7277 },
+  { 0x3145, G_UNICODE_NOT_PRESENT_OFFSET, 7281 },
+  { 0x3146, G_UNICODE_NOT_PRESENT_OFFSET, 7285 },
+  { 0x3147, G_UNICODE_NOT_PRESENT_OFFSET, 7289 },
+  { 0x3148, G_UNICODE_NOT_PRESENT_OFFSET, 7293 },
+  { 0x3149, G_UNICODE_NOT_PRESENT_OFFSET, 7297 },
+  { 0x314a, G_UNICODE_NOT_PRESENT_OFFSET, 7301 },
+  { 0x314b, G_UNICODE_NOT_PRESENT_OFFSET, 7305 },
+  { 0x314c, G_UNICODE_NOT_PRESENT_OFFSET, 7309 },
+  { 0x314d, G_UNICODE_NOT_PRESENT_OFFSET, 7313 },
+  { 0x314e, G_UNICODE_NOT_PRESENT_OFFSET, 7317 },
+  { 0x314f, G_UNICODE_NOT_PRESENT_OFFSET, 7321 },
+  { 0x3150, G_UNICODE_NOT_PRESENT_OFFSET, 7325 },
+  { 0x3151, G_UNICODE_NOT_PRESENT_OFFSET, 7329 },
+  { 0x3152, G_UNICODE_NOT_PRESENT_OFFSET, 7333 },
+  { 0x3153, G_UNICODE_NOT_PRESENT_OFFSET, 7337 },
+  { 0x3154, G_UNICODE_NOT_PRESENT_OFFSET, 7341 },
+  { 0x3155, G_UNICODE_NOT_PRESENT_OFFSET, 7345 },
+  { 0x3156, G_UNICODE_NOT_PRESENT_OFFSET, 7349 },
+  { 0x3157, G_UNICODE_NOT_PRESENT_OFFSET, 7353 },
+  { 0x3158, G_UNICODE_NOT_PRESENT_OFFSET, 7357 },
+  { 0x3159, G_UNICODE_NOT_PRESENT_OFFSET, 7361 },
+  { 0x315a, G_UNICODE_NOT_PRESENT_OFFSET, 7365 },
+  { 0x315b, G_UNICODE_NOT_PRESENT_OFFSET, 7369 },
+  { 0x315c, G_UNICODE_NOT_PRESENT_OFFSET, 7373 },
+  { 0x315d, G_UNICODE_NOT_PRESENT_OFFSET, 7377 },
+  { 0x315e, G_UNICODE_NOT_PRESENT_OFFSET, 7381 },
+  { 0x315f, G_UNICODE_NOT_PRESENT_OFFSET, 7385 },
+  { 0x3160, G_UNICODE_NOT_PRESENT_OFFSET, 7389 },
+  { 0x3161, G_UNICODE_NOT_PRESENT_OFFSET, 7393 },
+  { 0x3162, G_UNICODE_NOT_PRESENT_OFFSET, 7397 },
+  { 0x3163, G_UNICODE_NOT_PRESENT_OFFSET, 7401 },
+  { 0x3164, G_UNICODE_NOT_PRESENT_OFFSET, 7405 },
+  { 0x3165, G_UNICODE_NOT_PRESENT_OFFSET, 7409 },
+  { 0x3166, G_UNICODE_NOT_PRESENT_OFFSET, 7413 },
+  { 0x3167, G_UNICODE_NOT_PRESENT_OFFSET, 7417 },
+  { 0x3168, G_UNICODE_NOT_PRESENT_OFFSET, 7421 },
+  { 0x3169, G_UNICODE_NOT_PRESENT_OFFSET, 7425 },
+  { 0x316a, G_UNICODE_NOT_PRESENT_OFFSET, 7429 },
+  { 0x316b, G_UNICODE_NOT_PRESENT_OFFSET, 7433 },
+  { 0x316c, G_UNICODE_NOT_PRESENT_OFFSET, 7437 },
+  { 0x316d, G_UNICODE_NOT_PRESENT_OFFSET, 7441 },
+  { 0x316e, G_UNICODE_NOT_PRESENT_OFFSET, 7445 },
+  { 0x316f, G_UNICODE_NOT_PRESENT_OFFSET, 7449 },
+  { 0x3170, G_UNICODE_NOT_PRESENT_OFFSET, 7453 },
+  { 0x3171, G_UNICODE_NOT_PRESENT_OFFSET, 7457 },
+  { 0x3172, G_UNICODE_NOT_PRESENT_OFFSET, 7461 },
+  { 0x3173, G_UNICODE_NOT_PRESENT_OFFSET, 7465 },
+  { 0x3174, G_UNICODE_NOT_PRESENT_OFFSET, 7469 },
+  { 0x3175, G_UNICODE_NOT_PRESENT_OFFSET, 7473 },
+  { 0x3176, G_UNICODE_NOT_PRESENT_OFFSET, 7477 },
+  { 0x3177, G_UNICODE_NOT_PRESENT_OFFSET, 7481 },
+  { 0x3178, G_UNICODE_NOT_PRESENT_OFFSET, 7485 },
+  { 0x3179, G_UNICODE_NOT_PRESENT_OFFSET, 7489 },
+  { 0x317a, G_UNICODE_NOT_PRESENT_OFFSET, 7493 },
+  { 0x317b, G_UNICODE_NOT_PRESENT_OFFSET, 7497 },
+  { 0x317c, G_UNICODE_NOT_PRESENT_OFFSET, 7501 },
+  { 0x317d, G_UNICODE_NOT_PRESENT_OFFSET, 7505 },
+  { 0x317e, G_UNICODE_NOT_PRESENT_OFFSET, 7509 },
+  { 0x317f, G_UNICODE_NOT_PRESENT_OFFSET, 7513 },
+  { 0x3180, G_UNICODE_NOT_PRESENT_OFFSET, 7517 },
+  { 0x3181, G_UNICODE_NOT_PRESENT_OFFSET, 7521 },
+  { 0x3182, G_UNICODE_NOT_PRESENT_OFFSET, 7525 },
+  { 0x3183, G_UNICODE_NOT_PRESENT_OFFSET, 7529 },
+  { 0x3184, G_UNICODE_NOT_PRESENT_OFFSET, 7533 },
+  { 0x3185, G_UNICODE_NOT_PRESENT_OFFSET, 7537 },
+  { 0x3186, G_UNICODE_NOT_PRESENT_OFFSET, 7541 },
+  { 0x3187, G_UNICODE_NOT_PRESENT_OFFSET, 7545 },
+  { 0x3188, G_UNICODE_NOT_PRESENT_OFFSET, 7549 },
+  { 0x3189, G_UNICODE_NOT_PRESENT_OFFSET, 7553 },
+  { 0x318a, G_UNICODE_NOT_PRESENT_OFFSET, 7557 },
+  { 0x318b, G_UNICODE_NOT_PRESENT_OFFSET, 7561 },
+  { 0x318c, G_UNICODE_NOT_PRESENT_OFFSET, 7565 },
+  { 0x318d, G_UNICODE_NOT_PRESENT_OFFSET, 7569 },
+  { 0x318e, G_UNICODE_NOT_PRESENT_OFFSET, 7573 },
+  { 0x3192, G_UNICODE_NOT_PRESENT_OFFSET, 5903 },
+  { 0x3193, G_UNICODE_NOT_PRESENT_OFFSET, 5927 },
+  { 0x3194, G_UNICODE_NOT_PRESENT_OFFSET, 7577 },
+  { 0x3195, G_UNICODE_NOT_PRESENT_OFFSET, 7581 },
+  { 0x3196, G_UNICODE_NOT_PRESENT_OFFSET, 7585 },
+  { 0x3197, G_UNICODE_NOT_PRESENT_OFFSET, 7589 },
+  { 0x3198, G_UNICODE_NOT_PRESENT_OFFSET, 7593 },
+  { 0x3199, G_UNICODE_NOT_PRESENT_OFFSET, 7597 },
+  { 0x319a, G_UNICODE_NOT_PRESENT_OFFSET, 5919 },
+  { 0x319b, G_UNICODE_NOT_PRESENT_OFFSET, 7601 },
+  { 0x319c, G_UNICODE_NOT_PRESENT_OFFSET, 7605 },
+  { 0x319d, G_UNICODE_NOT_PRESENT_OFFSET, 7609 },
+  { 0x319e, G_UNICODE_NOT_PRESENT_OFFSET, 7613 },
+  { 0x319f, G_UNICODE_NOT_PRESENT_OFFSET, 5935 },
+  { 0x3200, G_UNICODE_NOT_PRESENT_OFFSET, 7617 },
+  { 0x3201, G_UNICODE_NOT_PRESENT_OFFSET, 7623 },
+  { 0x3202, G_UNICODE_NOT_PRESENT_OFFSET, 7629 },
+  { 0x3203, G_UNICODE_NOT_PRESENT_OFFSET, 7635 },
+  { 0x3204, G_UNICODE_NOT_PRESENT_OFFSET, 7641 },
+  { 0x3205, G_UNICODE_NOT_PRESENT_OFFSET, 7647 },
+  { 0x3206, G_UNICODE_NOT_PRESENT_OFFSET, 7653 },
+  { 0x3207, G_UNICODE_NOT_PRESENT_OFFSET, 7659 },
+  { 0x3208, G_UNICODE_NOT_PRESENT_OFFSET, 7665 },
+  { 0x3209, G_UNICODE_NOT_PRESENT_OFFSET, 7671 },
+  { 0x320a, G_UNICODE_NOT_PRESENT_OFFSET, 7677 },
+  { 0x320b, G_UNICODE_NOT_PRESENT_OFFSET, 7683 },
+  { 0x320c, G_UNICODE_NOT_PRESENT_OFFSET, 7689 },
+  { 0x320d, G_UNICODE_NOT_PRESENT_OFFSET, 7695 },
+  { 0x320e, G_UNICODE_NOT_PRESENT_OFFSET, 7701 },
+  { 0x320f, G_UNICODE_NOT_PRESENT_OFFSET, 7710 },
+  { 0x3210, G_UNICODE_NOT_PRESENT_OFFSET, 7719 },
+  { 0x3211, G_UNICODE_NOT_PRESENT_OFFSET, 7728 },
+  { 0x3212, G_UNICODE_NOT_PRESENT_OFFSET, 7737 },
+  { 0x3213, G_UNICODE_NOT_PRESENT_OFFSET, 7746 },
+  { 0x3214, G_UNICODE_NOT_PRESENT_OFFSET, 7755 },
+  { 0x3215, G_UNICODE_NOT_PRESENT_OFFSET, 7764 },
+  { 0x3216, G_UNICODE_NOT_PRESENT_OFFSET, 7773 },
+  { 0x3217, G_UNICODE_NOT_PRESENT_OFFSET, 7782 },
+  { 0x3218, G_UNICODE_NOT_PRESENT_OFFSET, 7791 },
+  { 0x3219, G_UNICODE_NOT_PRESENT_OFFSET, 7800 },
+  { 0x321a, G_UNICODE_NOT_PRESENT_OFFSET, 7809 },
+  { 0x321b, G_UNICODE_NOT_PRESENT_OFFSET, 7818 },
+  { 0x321c, G_UNICODE_NOT_PRESENT_OFFSET, 7827 },
+  { 0x3220, G_UNICODE_NOT_PRESENT_OFFSET, 7836 },
+  { 0x3221, G_UNICODE_NOT_PRESENT_OFFSET, 7842 },
+  { 0x3222, G_UNICODE_NOT_PRESENT_OFFSET, 7848 },
+  { 0x3223, G_UNICODE_NOT_PRESENT_OFFSET, 7854 },
+  { 0x3224, G_UNICODE_NOT_PRESENT_OFFSET, 7860 },
+  { 0x3225, G_UNICODE_NOT_PRESENT_OFFSET, 7866 },
+  { 0x3226, G_UNICODE_NOT_PRESENT_OFFSET, 7872 },
+  { 0x3227, G_UNICODE_NOT_PRESENT_OFFSET, 7878 },
+  { 0x3228, G_UNICODE_NOT_PRESENT_OFFSET, 7884 },
+  { 0x3229, G_UNICODE_NOT_PRESENT_OFFSET, 7890 },
+  { 0x322a, G_UNICODE_NOT_PRESENT_OFFSET, 7896 },
+  { 0x322b, G_UNICODE_NOT_PRESENT_OFFSET, 7902 },
+  { 0x322c, G_UNICODE_NOT_PRESENT_OFFSET, 7908 },
+  { 0x322d, G_UNICODE_NOT_PRESENT_OFFSET, 7914 },
+  { 0x322e, G_UNICODE_NOT_PRESENT_OFFSET, 7920 },
+  { 0x322f, G_UNICODE_NOT_PRESENT_OFFSET, 7926 },
+  { 0x3230, G_UNICODE_NOT_PRESENT_OFFSET, 7932 },
+  { 0x3231, G_UNICODE_NOT_PRESENT_OFFSET, 7938 },
+  { 0x3232, G_UNICODE_NOT_PRESENT_OFFSET, 7944 },
+  { 0x3233, G_UNICODE_NOT_PRESENT_OFFSET, 7950 },
+  { 0x3234, G_UNICODE_NOT_PRESENT_OFFSET, 7956 },
+  { 0x3235, G_UNICODE_NOT_PRESENT_OFFSET, 7962 },
+  { 0x3236, G_UNICODE_NOT_PRESENT_OFFSET, 7968 },
+  { 0x3237, G_UNICODE_NOT_PRESENT_OFFSET, 7974 },
+  { 0x3238, G_UNICODE_NOT_PRESENT_OFFSET, 7980 },
+  { 0x3239, G_UNICODE_NOT_PRESENT_OFFSET, 7986 },
+  { 0x323a, G_UNICODE_NOT_PRESENT_OFFSET, 7992 },
+  { 0x323b, G_UNICODE_NOT_PRESENT_OFFSET, 7998 },
+  { 0x323c, G_UNICODE_NOT_PRESENT_OFFSET, 8004 },
+  { 0x323d, G_UNICODE_NOT_PRESENT_OFFSET, 8010 },
+  { 0x323e, G_UNICODE_NOT_PRESENT_OFFSET, 8016 },
+  { 0x323f, G_UNICODE_NOT_PRESENT_OFFSET, 8022 },
+  { 0x3240, G_UNICODE_NOT_PRESENT_OFFSET, 8028 },
+  { 0x3241, G_UNICODE_NOT_PRESENT_OFFSET, 8034 },
+  { 0x3242, G_UNICODE_NOT_PRESENT_OFFSET, 8040 },
+  { 0x3243, G_UNICODE_NOT_PRESENT_OFFSET, 8046 },
+  { 0x3251, G_UNICODE_NOT_PRESENT_OFFSET, 8052 },
+  { 0x3252, G_UNICODE_NOT_PRESENT_OFFSET, 8055 },
+  { 0x3253, G_UNICODE_NOT_PRESENT_OFFSET, 8058 },
+  { 0x3254, G_UNICODE_NOT_PRESENT_OFFSET, 8061 },
+  { 0x3255, G_UNICODE_NOT_PRESENT_OFFSET, 8064 },
+  { 0x3256, G_UNICODE_NOT_PRESENT_OFFSET, 8067 },
+  { 0x3257, G_UNICODE_NOT_PRESENT_OFFSET, 8070 },
+  { 0x3258, G_UNICODE_NOT_PRESENT_OFFSET, 8073 },
+  { 0x3259, G_UNICODE_NOT_PRESENT_OFFSET, 8076 },
+  { 0x325a, G_UNICODE_NOT_PRESENT_OFFSET, 8079 },
+  { 0x325b, G_UNICODE_NOT_PRESENT_OFFSET, 8082 },
+  { 0x325c, G_UNICODE_NOT_PRESENT_OFFSET, 8085 },
+  { 0x325d, G_UNICODE_NOT_PRESENT_OFFSET, 8088 },
+  { 0x325e, G_UNICODE_NOT_PRESENT_OFFSET, 8091 },
+  { 0x325f, G_UNICODE_NOT_PRESENT_OFFSET, 8094 },
+  { 0x3260, G_UNICODE_NOT_PRESENT_OFFSET, 7201 },
+  { 0x3261, G_UNICODE_NOT_PRESENT_OFFSET, 7213 },
+  { 0x3262, G_UNICODE_NOT_PRESENT_OFFSET, 7225 },
+  { 0x3263, G_UNICODE_NOT_PRESENT_OFFSET, 7233 },
+  { 0x3264, G_UNICODE_NOT_PRESENT_OFFSET, 7265 },
+  { 0x3265, G_UNICODE_NOT_PRESENT_OFFSET, 7269 },
+  { 0x3266, G_UNICODE_NOT_PRESENT_OFFSET, 7281 },
+  { 0x3267, G_UNICODE_NOT_PRESENT_OFFSET, 7289 },
+  { 0x3268, G_UNICODE_NOT_PRESENT_OFFSET, 7293 },
+  { 0x3269, G_UNICODE_NOT_PRESENT_OFFSET, 7301 },
+  { 0x326a, G_UNICODE_NOT_PRESENT_OFFSET, 7305 },
+  { 0x326b, G_UNICODE_NOT_PRESENT_OFFSET, 7309 },
+  { 0x326c, G_UNICODE_NOT_PRESENT_OFFSET, 7313 },
+  { 0x326d, G_UNICODE_NOT_PRESENT_OFFSET, 7317 },
+  { 0x326e, G_UNICODE_NOT_PRESENT_OFFSET, 8097 },
+  { 0x326f, G_UNICODE_NOT_PRESENT_OFFSET, 8104 },
+  { 0x3270, G_UNICODE_NOT_PRESENT_OFFSET, 8111 },
+  { 0x3271, G_UNICODE_NOT_PRESENT_OFFSET, 8118 },
+  { 0x3272, G_UNICODE_NOT_PRESENT_OFFSET, 8125 },
+  { 0x3273, G_UNICODE_NOT_PRESENT_OFFSET, 8132 },
+  { 0x3274, G_UNICODE_NOT_PRESENT_OFFSET, 8139 },
+  { 0x3275, G_UNICODE_NOT_PRESENT_OFFSET, 8146 },
+  { 0x3276, G_UNICODE_NOT_PRESENT_OFFSET, 8153 },
+  { 0x3277, G_UNICODE_NOT_PRESENT_OFFSET, 8160 },
+  { 0x3278, G_UNICODE_NOT_PRESENT_OFFSET, 8167 },
+  { 0x3279, G_UNICODE_NOT_PRESENT_OFFSET, 8174 },
+  { 0x327a, G_UNICODE_NOT_PRESENT_OFFSET, 8181 },
+  { 0x327b, G_UNICODE_NOT_PRESENT_OFFSET, 8188 },
+  { 0x3280, G_UNICODE_NOT_PRESENT_OFFSET, 5903 },
+  { 0x3281, G_UNICODE_NOT_PRESENT_OFFSET, 5927 },
+  { 0x3282, G_UNICODE_NOT_PRESENT_OFFSET, 7577 },
+  { 0x3283, G_UNICODE_NOT_PRESENT_OFFSET, 7581 },
+  { 0x3284, G_UNICODE_NOT_PRESENT_OFFSET, 8195 },
+  { 0x3285, G_UNICODE_NOT_PRESENT_OFFSET, 8199 },
+  { 0x3286, G_UNICODE_NOT_PRESENT_OFFSET, 8203 },
+  { 0x3287, G_UNICODE_NOT_PRESENT_OFFSET, 5947 },
+  { 0x3288, G_UNICODE_NOT_PRESENT_OFFSET, 8207 },
+  { 0x3289, G_UNICODE_NOT_PRESENT_OFFSET, 5995 },
+  { 0x328a, G_UNICODE_NOT_PRESENT_OFFSET, 6195 },
+  { 0x328b, G_UNICODE_NOT_PRESENT_OFFSET, 6243 },
+  { 0x328c, G_UNICODE_NOT_PRESENT_OFFSET, 6239 },
+  { 0x328d, G_UNICODE_NOT_PRESENT_OFFSET, 6199 },
+  { 0x328e, G_UNICODE_NOT_PRESENT_OFFSET, 6567 },
+  { 0x328f, G_UNICODE_NOT_PRESENT_OFFSET, 6027 },
+  { 0x3290, G_UNICODE_NOT_PRESENT_OFFSET, 6187 },
+  { 0x3291, G_UNICODE_NOT_PRESENT_OFFSET, 8211 },
+  { 0x3292, G_UNICODE_NOT_PRESENT_OFFSET, 8215 },
+  { 0x3293, G_UNICODE_NOT_PRESENT_OFFSET, 8219 },
+  { 0x3294, G_UNICODE_NOT_PRESENT_OFFSET, 8223 },
+  { 0x3295, G_UNICODE_NOT_PRESENT_OFFSET, 8227 },
+  { 0x3296, G_UNICODE_NOT_PRESENT_OFFSET, 8231 },
+  { 0x3297, G_UNICODE_NOT_PRESENT_OFFSET, 8235 },
+  { 0x3298, G_UNICODE_NOT_PRESENT_OFFSET, 8239 },
+  { 0x3299, G_UNICODE_NOT_PRESENT_OFFSET, 8243 },
+  { 0x329a, G_UNICODE_NOT_PRESENT_OFFSET, 8247 },
+  { 0x329b, G_UNICODE_NOT_PRESENT_OFFSET, 6051 },
+  { 0x329c, G_UNICODE_NOT_PRESENT_OFFSET, 8251 },
+  { 0x329d, G_UNICODE_NOT_PRESENT_OFFSET, 8255 },
+  { 0x329e, G_UNICODE_NOT_PRESENT_OFFSET, 8259 },
+  { 0x329f, G_UNICODE_NOT_PRESENT_OFFSET, 8263 },
+  { 0x32a0, G_UNICODE_NOT_PRESENT_OFFSET, 8267 },
+  { 0x32a1, G_UNICODE_NOT_PRESENT_OFFSET, 8271 },
+  { 0x32a2, G_UNICODE_NOT_PRESENT_OFFSET, 8275 },
+  { 0x32a3, G_UNICODE_NOT_PRESENT_OFFSET, 8279 },
+  { 0x32a4, G_UNICODE_NOT_PRESENT_OFFSET, 7585 },
+  { 0x32a5, G_UNICODE_NOT_PRESENT_OFFSET, 7589 },
+  { 0x32a6, G_UNICODE_NOT_PRESENT_OFFSET, 7593 },
+  { 0x32a7, G_UNICODE_NOT_PRESENT_OFFSET, 8283 },
+  { 0x32a8, G_UNICODE_NOT_PRESENT_OFFSET, 8287 },
+  { 0x32a9, G_UNICODE_NOT_PRESENT_OFFSET, 8291 },
+  { 0x32aa, G_UNICODE_NOT_PRESENT_OFFSET, 8295 },
+  { 0x32ab, G_UNICODE_NOT_PRESENT_OFFSET, 8299 },
+  { 0x32ac, G_UNICODE_NOT_PRESENT_OFFSET, 8303 },
+  { 0x32ad, G_UNICODE_NOT_PRESENT_OFFSET, 8307 },
+  { 0x32ae, G_UNICODE_NOT_PRESENT_OFFSET, 8311 },
+  { 0x32af, G_UNICODE_NOT_PRESENT_OFFSET, 8315 },
+  { 0x32b0, G_UNICODE_NOT_PRESENT_OFFSET, 8319 },
+  { 0x32b1, G_UNICODE_NOT_PRESENT_OFFSET, 8323 },
+  { 0x32b2, G_UNICODE_NOT_PRESENT_OFFSET, 8326 },
+  { 0x32b3, G_UNICODE_NOT_PRESENT_OFFSET, 8329 },
+  { 0x32b4, G_UNICODE_NOT_PRESENT_OFFSET, 8332 },
+  { 0x32b5, G_UNICODE_NOT_PRESENT_OFFSET, 8335 },
+  { 0x32b6, G_UNICODE_NOT_PRESENT_OFFSET, 8338 },
+  { 0x32b7, G_UNICODE_NOT_PRESENT_OFFSET, 8341 },
+  { 0x32b8, G_UNICODE_NOT_PRESENT_OFFSET, 8344 },
+  { 0x32b9, G_UNICODE_NOT_PRESENT_OFFSET, 8347 },
+  { 0x32ba, G_UNICODE_NOT_PRESENT_OFFSET, 8350 },
+  { 0x32bb, G_UNICODE_NOT_PRESENT_OFFSET, 8353 },
+  { 0x32bc, G_UNICODE_NOT_PRESENT_OFFSET, 8356 },
+  { 0x32bd, G_UNICODE_NOT_PRESENT_OFFSET, 8359 },
+  { 0x32be, G_UNICODE_NOT_PRESENT_OFFSET, 8362 },
+  { 0x32bf, G_UNICODE_NOT_PRESENT_OFFSET, 8365 },
+  { 0x32c0, G_UNICODE_NOT_PRESENT_OFFSET, 8368 },
+  { 0x32c1, G_UNICODE_NOT_PRESENT_OFFSET, 8373 },
+  { 0x32c2, G_UNICODE_NOT_PRESENT_OFFSET, 8378 },
+  { 0x32c3, G_UNICODE_NOT_PRESENT_OFFSET, 8383 },
+  { 0x32c4, G_UNICODE_NOT_PRESENT_OFFSET, 8388 },
+  { 0x32c5, G_UNICODE_NOT_PRESENT_OFFSET, 8393 },
+  { 0x32c6, G_UNICODE_NOT_PRESENT_OFFSET, 8398 },
+  { 0x32c7, G_UNICODE_NOT_PRESENT_OFFSET, 8403 },
+  { 0x32c8, G_UNICODE_NOT_PRESENT_OFFSET, 8408 },
+  { 0x32c9, G_UNICODE_NOT_PRESENT_OFFSET, 8413 },
+  { 0x32ca, G_UNICODE_NOT_PRESENT_OFFSET, 8419 },
+  { 0x32cb, G_UNICODE_NOT_PRESENT_OFFSET, 8425 },
+  { 0x32d0, G_UNICODE_NOT_PRESENT_OFFSET, 8431 },
+  { 0x32d1, G_UNICODE_NOT_PRESENT_OFFSET, 8435 },
+  { 0x32d2, G_UNICODE_NOT_PRESENT_OFFSET, 8439 },
+  { 0x32d3, G_UNICODE_NOT_PRESENT_OFFSET, 8443 },
+  { 0x32d4, G_UNICODE_NOT_PRESENT_OFFSET, 8447 },
+  { 0x32d5, G_UNICODE_NOT_PRESENT_OFFSET, 8451 },
+  { 0x32d6, G_UNICODE_NOT_PRESENT_OFFSET, 8455 },
+  { 0x32d7, G_UNICODE_NOT_PRESENT_OFFSET, 8459 },
+  { 0x32d8, G_UNICODE_NOT_PRESENT_OFFSET, 8463 },
+  { 0x32d9, G_UNICODE_NOT_PRESENT_OFFSET, 8467 },
+  { 0x32da, G_UNICODE_NOT_PRESENT_OFFSET, 8471 },
+  { 0x32db, G_UNICODE_NOT_PRESENT_OFFSET, 8475 },
+  { 0x32dc, G_UNICODE_NOT_PRESENT_OFFSET, 8479 },
+  { 0x32dd, G_UNICODE_NOT_PRESENT_OFFSET, 8483 },
+  { 0x32de, G_UNICODE_NOT_PRESENT_OFFSET, 8487 },
+  { 0x32df, G_UNICODE_NOT_PRESENT_OFFSET, 8491 },
+  { 0x32e0, G_UNICODE_NOT_PRESENT_OFFSET, 8495 },
+  { 0x32e1, G_UNICODE_NOT_PRESENT_OFFSET, 8499 },
+  { 0x32e2, G_UNICODE_NOT_PRESENT_OFFSET, 8503 },
+  { 0x32e3, G_UNICODE_NOT_PRESENT_OFFSET, 8507 },
+  { 0x32e4, G_UNICODE_NOT_PRESENT_OFFSET, 8511 },
+  { 0x32e5, G_UNICODE_NOT_PRESENT_OFFSET, 8515 },
+  { 0x32e6, G_UNICODE_NOT_PRESENT_OFFSET, 8519 },
+  { 0x32e7, G_UNICODE_NOT_PRESENT_OFFSET, 8523 },
+  { 0x32e8, G_UNICODE_NOT_PRESENT_OFFSET, 8527 },
+  { 0x32e9, G_UNICODE_NOT_PRESENT_OFFSET, 8531 },
+  { 0x32ea, G_UNICODE_NOT_PRESENT_OFFSET, 8535 },
+  { 0x32eb, G_UNICODE_NOT_PRESENT_OFFSET, 8539 },
+  { 0x32ec, G_UNICODE_NOT_PRESENT_OFFSET, 8543 },
+  { 0x32ed, G_UNICODE_NOT_PRESENT_OFFSET, 8547 },
+  { 0x32ee, G_UNICODE_NOT_PRESENT_OFFSET, 8551 },
+  { 0x32ef, G_UNICODE_NOT_PRESENT_OFFSET, 8555 },
+  { 0x32f0, G_UNICODE_NOT_PRESENT_OFFSET, 8559 },
+  { 0x32f1, G_UNICODE_NOT_PRESENT_OFFSET, 8563 },
+  { 0x32f2, G_UNICODE_NOT_PRESENT_OFFSET, 8567 },
+  { 0x32f3, G_UNICODE_NOT_PRESENT_OFFSET, 8571 },
+  { 0x32f4, G_UNICODE_NOT_PRESENT_OFFSET, 8575 },
+  { 0x32f5, G_UNICODE_NOT_PRESENT_OFFSET, 8579 },
+  { 0x32f6, G_UNICODE_NOT_PRESENT_OFFSET, 8583 },
+  { 0x32f7, G_UNICODE_NOT_PRESENT_OFFSET, 8587 },
+  { 0x32f8, G_UNICODE_NOT_PRESENT_OFFSET, 8591 },
+  { 0x32f9, G_UNICODE_NOT_PRESENT_OFFSET, 8595 },
+  { 0x32fa, G_UNICODE_NOT_PRESENT_OFFSET, 8599 },
+  { 0x32fb, G_UNICODE_NOT_PRESENT_OFFSET, 8603 },
+  { 0x32fc, G_UNICODE_NOT_PRESENT_OFFSET, 8607 },
+  { 0x32fd, G_UNICODE_NOT_PRESENT_OFFSET, 8611 },
+  { 0x32fe, G_UNICODE_NOT_PRESENT_OFFSET, 8615 },
+  { 0x3300, G_UNICODE_NOT_PRESENT_OFFSET, 8619 },
+  { 0x3301, G_UNICODE_NOT_PRESENT_OFFSET, 8635 },
+  { 0x3302, G_UNICODE_NOT_PRESENT_OFFSET, 8648 },
+  { 0x3303, G_UNICODE_NOT_PRESENT_OFFSET, 8664 },
+  { 0x3304, G_UNICODE_NOT_PRESENT_OFFSET, 8674 },
+  { 0x3305, G_UNICODE_NOT_PRESENT_OFFSET, 8690 },
+  { 0x3306, G_UNICODE_NOT_PRESENT_OFFSET, 8700 },
+  { 0x3307, G_UNICODE_NOT_PRESENT_OFFSET, 8710 },
+  { 0x3308, G_UNICODE_NOT_PRESENT_OFFSET, 8729 },
+  { 0x3309, G_UNICODE_NOT_PRESENT_OFFSET, 8742 },
+  { 0x330a, G_UNICODE_NOT_PRESENT_OFFSET, 8752 },
+  { 0x330b, G_UNICODE_NOT_PRESENT_OFFSET, 8762 },
+  { 0x330c, G_UNICODE_NOT_PRESENT_OFFSET, 8772 },
+  { 0x330d, G_UNICODE_NOT_PRESENT_OFFSET, 8785 },
+  { 0x330e, G_UNICODE_NOT_PRESENT_OFFSET, 8798 },
+  { 0x330f, G_UNICODE_NOT_PRESENT_OFFSET, 8811 },
+  { 0x3310, G_UNICODE_NOT_PRESENT_OFFSET, 8824 },
+  { 0x3311, G_UNICODE_NOT_PRESENT_OFFSET, 8837 },
+  { 0x3312, G_UNICODE_NOT_PRESENT_OFFSET, 8850 },
+  { 0x3313, G_UNICODE_NOT_PRESENT_OFFSET, 8863 },
+  { 0x3314, G_UNICODE_NOT_PRESENT_OFFSET, 8882 },
+  { 0x3315, G_UNICODE_NOT_PRESENT_OFFSET, 8889 },
+  { 0x3316, G_UNICODE_NOT_PRESENT_OFFSET, 8908 },
+  { 0x3317, G_UNICODE_NOT_PRESENT_OFFSET, 8927 },
+  { 0x3318, G_UNICODE_NOT_PRESENT_OFFSET, 8943 },
+  { 0x3319, G_UNICODE_NOT_PRESENT_OFFSET, 8956 },
+  { 0x331a, G_UNICODE_NOT_PRESENT_OFFSET, 8975 },
+  { 0x331b, G_UNICODE_NOT_PRESENT_OFFSET, 8994 },
+  { 0x331c, G_UNICODE_NOT_PRESENT_OFFSET, 9007 },
+  { 0x331d, G_UNICODE_NOT_PRESENT_OFFSET, 9017 },
+  { 0x331e, G_UNICODE_NOT_PRESENT_OFFSET, 9027 },
+  { 0x331f, G_UNICODE_NOT_PRESENT_OFFSET, 9040 },
+  { 0x3320, G_UNICODE_NOT_PRESENT_OFFSET, 9053 },
+  { 0x3321, G_UNICODE_NOT_PRESENT_OFFSET, 9069 },
+  { 0x3322, G_UNICODE_NOT_PRESENT_OFFSET, 9085 },
+  { 0x3323, G_UNICODE_NOT_PRESENT_OFFSET, 9095 },
+  { 0x3324, G_UNICODE_NOT_PRESENT_OFFSET, 9105 },
+  { 0x3325, G_UNICODE_NOT_PRESENT_OFFSET, 9118 },
+  { 0x3326, G_UNICODE_NOT_PRESENT_OFFSET, 9128 },
+  { 0x3327, G_UNICODE_NOT_PRESENT_OFFSET, 9138 },
+  { 0x3328, G_UNICODE_NOT_PRESENT_OFFSET, 9145 },
+  { 0x3329, G_UNICODE_NOT_PRESENT_OFFSET, 9152 },
+  { 0x332a, G_UNICODE_NOT_PRESENT_OFFSET, 9162 },
+  { 0x332b, G_UNICODE_NOT_PRESENT_OFFSET, 9172 },
+  { 0x332c, G_UNICODE_NOT_PRESENT_OFFSET, 9191 },
+  { 0x332d, G_UNICODE_NOT_PRESENT_OFFSET, 9204 },
+  { 0x332e, G_UNICODE_NOT_PRESENT_OFFSET, 9220 },
+  { 0x332f, G_UNICODE_NOT_PRESENT_OFFSET, 9239 },
+  { 0x3330, G_UNICODE_NOT_PRESENT_OFFSET, 9252 },
+  { 0x3331, G_UNICODE_NOT_PRESENT_OFFSET, 9262 },
+  { 0x3332, G_UNICODE_NOT_PRESENT_OFFSET, 9272 },
+  { 0x3333, G_UNICODE_NOT_PRESENT_OFFSET, 9291 },
+  { 0x3334, G_UNICODE_NOT_PRESENT_OFFSET, 9304 },
+  { 0x3335, G_UNICODE_NOT_PRESENT_OFFSET, 9323 },
+  { 0x3336, G_UNICODE_NOT_PRESENT_OFFSET, 9333 },
+  { 0x3337, G_UNICODE_NOT_PRESENT_OFFSET, 9349 },
+  { 0x3338, G_UNICODE_NOT_PRESENT_OFFSET, 9359 },
+  { 0x3339, G_UNICODE_NOT_PRESENT_OFFSET, 9372 },
+  { 0x333a, G_UNICODE_NOT_PRESENT_OFFSET, 9382 },
+  { 0x333b, G_UNICODE_NOT_PRESENT_OFFSET, 9395 },
+  { 0x333c, G_UNICODE_NOT_PRESENT_OFFSET, 9411 },
+  { 0x333d, G_UNICODE_NOT_PRESENT_OFFSET, 9424 },
+  { 0x333e, G_UNICODE_NOT_PRESENT_OFFSET, 9440 },
+  { 0x333f, G_UNICODE_NOT_PRESENT_OFFSET, 9453 },
+  { 0x3340, G_UNICODE_NOT_PRESENT_OFFSET, 9460 },
+  { 0x3341, G_UNICODE_NOT_PRESENT_OFFSET, 9476 },
+  { 0x3342, G_UNICODE_NOT_PRESENT_OFFSET, 9486 },
+  { 0x3343, G_UNICODE_NOT_PRESENT_OFFSET, 9496 },
+  { 0x3344, G_UNICODE_NOT_PRESENT_OFFSET, 9509 },
+  { 0x3345, G_UNICODE_NOT_PRESENT_OFFSET, 9519 },
+  { 0x3346, G_UNICODE_NOT_PRESENT_OFFSET, 9529 },
+  { 0x3347, G_UNICODE_NOT_PRESENT_OFFSET, 9539 },
+  { 0x3348, G_UNICODE_NOT_PRESENT_OFFSET, 9555 },
+  { 0x3349, G_UNICODE_NOT_PRESENT_OFFSET, 9568 },
+  { 0x334a, G_UNICODE_NOT_PRESENT_OFFSET, 9575 },
+  { 0x334b, G_UNICODE_NOT_PRESENT_OFFSET, 9594 },
+  { 0x334c, G_UNICODE_NOT_PRESENT_OFFSET, 9604 },
+  { 0x334d, G_UNICODE_NOT_PRESENT_OFFSET, 9620 },
+  { 0x334e, G_UNICODE_NOT_PRESENT_OFFSET, 9633 },
+  { 0x334f, G_UNICODE_NOT_PRESENT_OFFSET, 9646 },
+  { 0x3350, G_UNICODE_NOT_PRESENT_OFFSET, 9656 },
+  { 0x3351, G_UNICODE_NOT_PRESENT_OFFSET, 9666 },
+  { 0x3352, G_UNICODE_NOT_PRESENT_OFFSET, 9679 },
+  { 0x3353, G_UNICODE_NOT_PRESENT_OFFSET, 9686 },
+  { 0x3354, G_UNICODE_NOT_PRESENT_OFFSET, 9699 },
+  { 0x3355, G_UNICODE_NOT_PRESENT_OFFSET, 9715 },
+  { 0x3356, G_UNICODE_NOT_PRESENT_OFFSET, 9722 },
+  { 0x3357, G_UNICODE_NOT_PRESENT_OFFSET, 9741 },
+  { 0x3358, G_UNICODE_NOT_PRESENT_OFFSET, 9751 },
+  { 0x3359, G_UNICODE_NOT_PRESENT_OFFSET, 9756 },
+  { 0x335a, G_UNICODE_NOT_PRESENT_OFFSET, 9761 },
+  { 0x335b, G_UNICODE_NOT_PRESENT_OFFSET, 9766 },
+  { 0x335c, G_UNICODE_NOT_PRESENT_OFFSET, 9771 },
+  { 0x335d, G_UNICODE_NOT_PRESENT_OFFSET, 9776 },
+  { 0x335e, G_UNICODE_NOT_PRESENT_OFFSET, 9781 },
+  { 0x335f, G_UNICODE_NOT_PRESENT_OFFSET, 9786 },
+  { 0x3360, G_UNICODE_NOT_PRESENT_OFFSET, 9791 },
+  { 0x3361, G_UNICODE_NOT_PRESENT_OFFSET, 9796 },
+  { 0x3362, G_UNICODE_NOT_PRESENT_OFFSET, 9801 },
+  { 0x3363, G_UNICODE_NOT_PRESENT_OFFSET, 9807 },
+  { 0x3364, G_UNICODE_NOT_PRESENT_OFFSET, 9813 },
+  { 0x3365, G_UNICODE_NOT_PRESENT_OFFSET, 9819 },
+  { 0x3366, G_UNICODE_NOT_PRESENT_OFFSET, 9825 },
+  { 0x3367, G_UNICODE_NOT_PRESENT_OFFSET, 9831 },
+  { 0x3368, G_UNICODE_NOT_PRESENT_OFFSET, 9837 },
+  { 0x3369, G_UNICODE_NOT_PRESENT_OFFSET, 9843 },
+  { 0x336a, G_UNICODE_NOT_PRESENT_OFFSET, 9849 },
+  { 0x336b, G_UNICODE_NOT_PRESENT_OFFSET, 9855 },
+  { 0x336c, G_UNICODE_NOT_PRESENT_OFFSET, 9861 },
+  { 0x336d, G_UNICODE_NOT_PRESENT_OFFSET, 9867 },
+  { 0x336e, G_UNICODE_NOT_PRESENT_OFFSET, 9873 },
+  { 0x336f, G_UNICODE_NOT_PRESENT_OFFSET, 9879 },
+  { 0x3370, G_UNICODE_NOT_PRESENT_OFFSET, 9885 },
+  { 0x3371, G_UNICODE_NOT_PRESENT_OFFSET, 9891 },
+  { 0x3372, G_UNICODE_NOT_PRESENT_OFFSET, 9895 },
+  { 0x3373, G_UNICODE_NOT_PRESENT_OFFSET, 9898 },
+  { 0x3374, G_UNICODE_NOT_PRESENT_OFFSET, 9901 },
+  { 0x3375, G_UNICODE_NOT_PRESENT_OFFSET, 9905 },
+  { 0x3376, G_UNICODE_NOT_PRESENT_OFFSET, 9908 },
+  { 0x337b, G_UNICODE_NOT_PRESENT_OFFSET, 9911 },
+  { 0x337c, G_UNICODE_NOT_PRESENT_OFFSET, 9918 },
+  { 0x337d, G_UNICODE_NOT_PRESENT_OFFSET, 9925 },
+  { 0x337e, G_UNICODE_NOT_PRESENT_OFFSET, 9932 },
+  { 0x337f, G_UNICODE_NOT_PRESENT_OFFSET, 9939 },
+  { 0x3380, G_UNICODE_NOT_PRESENT_OFFSET, 9952 },
+  { 0x3381, G_UNICODE_NOT_PRESENT_OFFSET, 9955 },
+  { 0x3382, G_UNICODE_NOT_PRESENT_OFFSET, 9958 },
+  { 0x3383, G_UNICODE_NOT_PRESENT_OFFSET, 9962 },
+  { 0x3384, G_UNICODE_NOT_PRESENT_OFFSET, 9965 },
+  { 0x3385, G_UNICODE_NOT_PRESENT_OFFSET, 9968 },
+  { 0x3386, G_UNICODE_NOT_PRESENT_OFFSET, 9971 },
+  { 0x3387, G_UNICODE_NOT_PRESENT_OFFSET, 9974 },
+  { 0x3388, G_UNICODE_NOT_PRESENT_OFFSET, 9977 },
+  { 0x3389, G_UNICODE_NOT_PRESENT_OFFSET, 9981 },
+  { 0x338a, G_UNICODE_NOT_PRESENT_OFFSET, 9986 },
+  { 0x338b, G_UNICODE_NOT_PRESENT_OFFSET, 9989 },
+  { 0x338c, G_UNICODE_NOT_PRESENT_OFFSET, 9992 },
+  { 0x338d, G_UNICODE_NOT_PRESENT_OFFSET, 9996 },
+  { 0x338e, G_UNICODE_NOT_PRESENT_OFFSET, 10000 },
+  { 0x338f, G_UNICODE_NOT_PRESENT_OFFSET, 10003 },
+  { 0x3390, G_UNICODE_NOT_PRESENT_OFFSET, 10006 },
+  { 0x3391, G_UNICODE_NOT_PRESENT_OFFSET, 10009 },
+  { 0x3392, G_UNICODE_NOT_PRESENT_OFFSET, 10013 },
+  { 0x3393, G_UNICODE_NOT_PRESENT_OFFSET, 10017 },
+  { 0x3394, G_UNICODE_NOT_PRESENT_OFFSET, 10021 },
+  { 0x3395, G_UNICODE_NOT_PRESENT_OFFSET, 10025 },
+  { 0x3396, G_UNICODE_NOT_PRESENT_OFFSET, 10029 },
+  { 0x3397, G_UNICODE_NOT_PRESENT_OFFSET, 10032 },
+  { 0x3398, G_UNICODE_NOT_PRESENT_OFFSET, 10035 },
+  { 0x3399, G_UNICODE_NOT_PRESENT_OFFSET, 10038 },
+  { 0x339a, G_UNICODE_NOT_PRESENT_OFFSET, 10041 },
+  { 0x339b, G_UNICODE_NOT_PRESENT_OFFSET, 10044 },
+  { 0x339c, G_UNICODE_NOT_PRESENT_OFFSET, 10048 },
+  { 0x339d, G_UNICODE_NOT_PRESENT_OFFSET, 10051 },
+  { 0x339e, G_UNICODE_NOT_PRESENT_OFFSET, 10054 },
+  { 0x339f, G_UNICODE_NOT_PRESENT_OFFSET, 10057 },
+  { 0x33a0, G_UNICODE_NOT_PRESENT_OFFSET, 10061 },
+  { 0x33a1, G_UNICODE_NOT_PRESENT_OFFSET, 10065 },
+  { 0x33a2, G_UNICODE_NOT_PRESENT_OFFSET, 10068 },
+  { 0x33a3, G_UNICODE_NOT_PRESENT_OFFSET, 10072 },
+  { 0x33a4, G_UNICODE_NOT_PRESENT_OFFSET, 10076 },
+  { 0x33a5, G_UNICODE_NOT_PRESENT_OFFSET, 10080 },
+  { 0x33a6, G_UNICODE_NOT_PRESENT_OFFSET, 10083 },
+  { 0x33a7, G_UNICODE_NOT_PRESENT_OFFSET, 10087 },
+  { 0x33a8, G_UNICODE_NOT_PRESENT_OFFSET, 10093 },
+  { 0x33a9, G_UNICODE_NOT_PRESENT_OFFSET, 10100 },
+  { 0x33aa, G_UNICODE_NOT_PRESENT_OFFSET, 10103 },
+  { 0x33ab, G_UNICODE_NOT_PRESENT_OFFSET, 10107 },
+  { 0x33ac, G_UNICODE_NOT_PRESENT_OFFSET, 10111 },
+  { 0x33ad, G_UNICODE_NOT_PRESENT_OFFSET, 10115 },
+  { 0x33ae, G_UNICODE_NOT_PRESENT_OFFSET, 10119 },
+  { 0x33af, G_UNICODE_NOT_PRESENT_OFFSET, 10127 },
+  { 0x33b0, G_UNICODE_NOT_PRESENT_OFFSET, 10136 },
+  { 0x33b1, G_UNICODE_NOT_PRESENT_OFFSET, 10139 },
+  { 0x33b2, G_UNICODE_NOT_PRESENT_OFFSET, 10142 },
+  { 0x33b3, G_UNICODE_NOT_PRESENT_OFFSET, 10146 },
+  { 0x33b4, G_UNICODE_NOT_PRESENT_OFFSET, 10149 },
+  { 0x33b5, G_UNICODE_NOT_PRESENT_OFFSET, 10152 },
+  { 0x33b6, G_UNICODE_NOT_PRESENT_OFFSET, 10155 },
+  { 0x33b7, G_UNICODE_NOT_PRESENT_OFFSET, 10159 },
+  { 0x33b8, G_UNICODE_NOT_PRESENT_OFFSET, 10162 },
+  { 0x33b9, G_UNICODE_NOT_PRESENT_OFFSET, 10165 },
+  { 0x33ba, G_UNICODE_NOT_PRESENT_OFFSET, 10168 },
+  { 0x33bb, G_UNICODE_NOT_PRESENT_OFFSET, 10171 },
+  { 0x33bc, G_UNICODE_NOT_PRESENT_OFFSET, 10174 },
+  { 0x33bd, G_UNICODE_NOT_PRESENT_OFFSET, 10178 },
+  { 0x33be, G_UNICODE_NOT_PRESENT_OFFSET, 10181 },
+  { 0x33bf, G_UNICODE_NOT_PRESENT_OFFSET, 10184 },
+  { 0x33c0, G_UNICODE_NOT_PRESENT_OFFSET, 10187 },
+  { 0x33c1, G_UNICODE_NOT_PRESENT_OFFSET, 10191 },
+  { 0x33c2, G_UNICODE_NOT_PRESENT_OFFSET, 10195 },
+  { 0x33c3, G_UNICODE_NOT_PRESENT_OFFSET, 10200 },
+  { 0x33c4, G_UNICODE_NOT_PRESENT_OFFSET, 10203 },
+  { 0x33c5, G_UNICODE_NOT_PRESENT_OFFSET, 10206 },
+  { 0x33c6, G_UNICODE_NOT_PRESENT_OFFSET, 10209 },
+  { 0x33c7, G_UNICODE_NOT_PRESENT_OFFSET, 10216 },
+  { 0x33c8, G_UNICODE_NOT_PRESENT_OFFSET, 10220 },
+  { 0x33c9, G_UNICODE_NOT_PRESENT_OFFSET, 10223 },
+  { 0x33ca, G_UNICODE_NOT_PRESENT_OFFSET, 10226 },
+  { 0x33cb, G_UNICODE_NOT_PRESENT_OFFSET, 10229 },
+  { 0x33cc, G_UNICODE_NOT_PRESENT_OFFSET, 10232 },
+  { 0x33cd, G_UNICODE_NOT_PRESENT_OFFSET, 10235 },
+  { 0x33ce, G_UNICODE_NOT_PRESENT_OFFSET, 10238 },
+  { 0x33cf, G_UNICODE_NOT_PRESENT_OFFSET, 10241 },
+  { 0x33d0, G_UNICODE_NOT_PRESENT_OFFSET, 10244 },
+  { 0x33d1, G_UNICODE_NOT_PRESENT_OFFSET, 10247 },
+  { 0x33d2, G_UNICODE_NOT_PRESENT_OFFSET, 10250 },
+  { 0x33d3, G_UNICODE_NOT_PRESENT_OFFSET, 10254 },
+  { 0x33d4, G_UNICODE_NOT_PRESENT_OFFSET, 10257 },
+  { 0x33d5, G_UNICODE_NOT_PRESENT_OFFSET, 10260 },
+  { 0x33d6, G_UNICODE_NOT_PRESENT_OFFSET, 10264 },
+  { 0x33d7, G_UNICODE_NOT_PRESENT_OFFSET, 10268 },
+  { 0x33d8, G_UNICODE_NOT_PRESENT_OFFSET, 10271 },
+  { 0x33d9, G_UNICODE_NOT_PRESENT_OFFSET, 10276 },
+  { 0x33da, G_UNICODE_NOT_PRESENT_OFFSET, 10280 },
+  { 0x33db, G_UNICODE_NOT_PRESENT_OFFSET, 10283 },
+  { 0x33dc, G_UNICODE_NOT_PRESENT_OFFSET, 10286 },
+  { 0x33dd, G_UNICODE_NOT_PRESENT_OFFSET, 10289 },
+  { 0x33e0, G_UNICODE_NOT_PRESENT_OFFSET, 10292 },
+  { 0x33e1, G_UNICODE_NOT_PRESENT_OFFSET, 10297 },
+  { 0x33e2, G_UNICODE_NOT_PRESENT_OFFSET, 10302 },
+  { 0x33e3, G_UNICODE_NOT_PRESENT_OFFSET, 10307 },
+  { 0x33e4, G_UNICODE_NOT_PRESENT_OFFSET, 10312 },
+  { 0x33e5, G_UNICODE_NOT_PRESENT_OFFSET, 10317 },
+  { 0x33e6, G_UNICODE_NOT_PRESENT_OFFSET, 10322 },
+  { 0x33e7, G_UNICODE_NOT_PRESENT_OFFSET, 10327 },
+  { 0x33e8, G_UNICODE_NOT_PRESENT_OFFSET, 10332 },
+  { 0x33e9, G_UNICODE_NOT_PRESENT_OFFSET, 10337 },
+  { 0x33ea, G_UNICODE_NOT_PRESENT_OFFSET, 10343 },
+  { 0x33eb, G_UNICODE_NOT_PRESENT_OFFSET, 10349 },
+  { 0x33ec, G_UNICODE_NOT_PRESENT_OFFSET, 10355 },
+  { 0x33ed, G_UNICODE_NOT_PRESENT_OFFSET, 10361 },
+  { 0x33ee, G_UNICODE_NOT_PRESENT_OFFSET, 10367 },
+  { 0x33ef, G_UNICODE_NOT_PRESENT_OFFSET, 10373 },
+  { 0x33f0, G_UNICODE_NOT_PRESENT_OFFSET, 10379 },
+  { 0x33f1, G_UNICODE_NOT_PRESENT_OFFSET, 10385 },
+  { 0x33f2, G_UNICODE_NOT_PRESENT_OFFSET, 10391 },
+  { 0x33f3, G_UNICODE_NOT_PRESENT_OFFSET, 10397 },
+  { 0x33f4, G_UNICODE_NOT_PRESENT_OFFSET, 10403 },
+  { 0x33f5, G_UNICODE_NOT_PRESENT_OFFSET, 10409 },
+  { 0x33f6, G_UNICODE_NOT_PRESENT_OFFSET, 10415 },
+  { 0x33f7, G_UNICODE_NOT_PRESENT_OFFSET, 10421 },
+  { 0x33f8, G_UNICODE_NOT_PRESENT_OFFSET, 10427 },
+  { 0x33f9, G_UNICODE_NOT_PRESENT_OFFSET, 10433 },
+  { 0x33fa, G_UNICODE_NOT_PRESENT_OFFSET, 10439 },
+  { 0x33fb, G_UNICODE_NOT_PRESENT_OFFSET, 10445 },
+  { 0x33fc, G_UNICODE_NOT_PRESENT_OFFSET, 10451 },
+  { 0x33fd, G_UNICODE_NOT_PRESENT_OFFSET, 10457 },
+  { 0x33fe, G_UNICODE_NOT_PRESENT_OFFSET, 10463 },
+  { 0xf900, 10469, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf901, 10473, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf902, 6535, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf903, 10477, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf904, 10481, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf905, 10485, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf906, 10489, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf907, 6751, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf908, 6751, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf909, 10493, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf90a, 6567, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf90b, 10497, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf90c, 10501, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf90d, 10505, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf90e, 10509, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf90f, 10513, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf910, 10517, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf911, 10521, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf912, 10525, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf913, 10529, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf914, 10533, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf915, 10537, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf916, 10541, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf917, 10545, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf918, 10549, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf919, 10553, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf91a, 10557, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf91b, 10561, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf91c, 10565, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf91d, 10569, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf91e, 10573, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf91f, 10577, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf920, 10581, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf921, 10585, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf922, 10589, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf923, 10593, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf924, 10597, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf925, 10601, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf926, 10605, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf927, 10609, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf928, 10613, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf929, 10617, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf92a, 10621, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf92b, 10625, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf92c, 10629, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf92d, 10633, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf92e, 10637, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf92f, 10641, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf930, 10645, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf931, 10649, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf932, 10653, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf933, 10657, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf934, 6399, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf935, 10661, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf936, 10665, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf937, 10669, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf938, 10673, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf939, 10677, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf93a, 10681, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf93b, 10685, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf93c, 10689, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf93d, 10693, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf93e, 10697, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf93f, 10701, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf940, 6691, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf941, 10705, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf942, 10709, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf943, 10713, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf944, 10717, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf945, 10721, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf946, 10725, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf947, 10729, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf948, 10733, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf949, 10737, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf94a, 10741, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf94b, 10745, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf94c, 10749, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf94d, 10753, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf94e, 10757, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf94f, 10761, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf950, 10765, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf951, 10769, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf952, 10773, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf953, 10777, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf954, 10781, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf955, 10785, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf956, 10789, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf957, 10793, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf958, 10797, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf959, 10801, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf95a, 10805, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf95b, 10809, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf95c, 10533, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf95d, 10813, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf95e, 10817, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf95f, 10821, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf960, 10825, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf961, 10829, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf962, 10833, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf963, 10837, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf964, 10841, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf965, 10845, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf966, 10849, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf967, 10853, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf968, 10857, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf969, 10861, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf96a, 10865, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf96b, 10869, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf96c, 10873, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf96d, 10877, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf96e, 10881, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf96f, 10885, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf970, 10889, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf971, 6543, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf972, 10893, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf973, 10897, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf974, 10901, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf975, 10905, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf976, 10909, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf977, 10913, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf978, 10917, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf979, 10921, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf97a, 10925, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf97b, 10929, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf97c, 10933, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf97d, 10937, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf97e, 10941, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf97f, 10945, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf980, 10949, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf981, 6051, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf982, 10953, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf983, 10957, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf984, 10961, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf985, 10965, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf986, 10969, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf987, 10973, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf988, 10977, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf989, 10981, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf98a, 5975, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf98b, 10985, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf98c, 10989, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf98d, 10993, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf98e, 10997, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf98f, 11001, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf990, 11005, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf991, 11009, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf992, 11013, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf993, 11017, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf994, 11021, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf995, 11025, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf996, 11029, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf997, 11033, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf998, 11037, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf999, 11041, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf99a, 11045, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf99b, 11049, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf99c, 11053, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf99d, 11057, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf99e, 11061, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf99f, 11065, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a0, 11069, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a1, 10885, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a2, 11073, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a3, 11077, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a4, 11081, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a5, 11085, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a6, 11089, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a7, 11093, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a8, 11097, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9a9, 11101, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9aa, 10821, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ab, 11105, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ac, 11109, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ad, 11113, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ae, 11117, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9af, 11121, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b0, 11125, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b1, 11129, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b2, 11133, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b3, 11137, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b4, 11141, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b5, 11145, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b6, 11149, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b7, 11153, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b8, 11157, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9b9, 11161, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ba, 11165, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9bb, 11169, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9bc, 11173, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9bd, 11177, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9be, 11181, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9bf, 10533, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c0, 11185, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c1, 11189, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c2, 11193, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c3, 11197, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c4, 6747, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c5, 11201, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c6, 11205, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c7, 11209, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c8, 11213, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9c9, 11217, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ca, 11221, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9cb, 11225, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9cc, 11229, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9cd, 11233, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ce, 11237, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9cf, 11241, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d0, 11245, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d1, 8199, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d2, 11249, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d3, 11253, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d4, 11257, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d5, 11261, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d6, 11265, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d7, 11269, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d8, 11273, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9d9, 11277, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9da, 11281, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9db, 10829, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9dc, 11285, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9dd, 11289, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9de, 11293, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9df, 11297, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e0, 11301, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e1, 11305, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e2, 11309, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e3, 11313, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e4, 11317, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e5, 11321, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e6, 11325, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e7, 11329, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e8, 11333, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9e9, 6563, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ea, 11337, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9eb, 11341, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ec, 11345, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ed, 11349, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ee, 11353, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ef, 11357, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f0, 11361, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f1, 11365, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f2, 11369, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f3, 11373, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f4, 11377, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f5, 11381, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f6, 11385, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f7, 6367, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f8, 11389, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9f9, 11393, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9fa, 11397, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9fb, 11401, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9fc, 11405, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9fd, 11409, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9fe, 11413, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xf9ff, 11417, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa00, 11421, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa01, 11425, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa02, 11429, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa03, 11433, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa04, 11437, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa05, 11441, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa06, 11445, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa07, 11449, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa08, 6475, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa09, 11453, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa0a, 6487, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa0b, 11457, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa0c, 11461, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa0d, 11465, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa10, 11469, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa12, 11473, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa15, 11477, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa16, 11481, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa17, 11485, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa18, 11489, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa19, 11493, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa1a, 11497, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa1b, 11501, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa1c, 11505, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa1d, 11509, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa1e, 6395, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa20, 11513, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa22, 11517, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa25, 11521, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa26, 11525, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa2a, 11529, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa2b, 11533, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa2c, 11537, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa2d, 11541, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa30, 11545, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa31, 11549, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa32, 11553, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa33, 11557, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa34, 11561, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa35, 11565, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa36, 11569, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa37, 11573, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa38, 11577, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa39, 11581, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa3a, 11585, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa3b, 11589, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa3c, 6079, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa3d, 11593, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa3e, 11597, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa3f, 11601, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa40, 11605, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa41, 11609, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa42, 11613, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa43, 11617, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa44, 11621, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa45, 11625, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa46, 11629, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa47, 11633, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa48, 11637, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa49, 11641, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa4a, 11645, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa4b, 11649, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa4c, 8219, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa4d, 11653, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa4e, 11657, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa4f, 11661, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa50, 11665, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa51, 8235, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa52, 11669, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa53, 11673, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa54, 11677, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa55, 11681, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa56, 11685, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa57, 11029, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa58, 11689, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa59, 11693, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa5a, 11697, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa5b, 11701, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa5c, 11705, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa5d, 11709, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa5e, 11709, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa5f, 11713, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa60, 11717, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa61, 11721, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa62, 11725, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa63, 11729, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa64, 11733, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa65, 11737, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa66, 11741, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa67, 11521, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa68, 11745, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa69, 11749, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfa6a, 11753, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb00, G_UNICODE_NOT_PRESENT_OFFSET, 11757 },
+  { 0xfb01, G_UNICODE_NOT_PRESENT_OFFSET, 11760 },
+  { 0xfb02, G_UNICODE_NOT_PRESENT_OFFSET, 11763 },
+  { 0xfb03, G_UNICODE_NOT_PRESENT_OFFSET, 11766 },
+  { 0xfb04, G_UNICODE_NOT_PRESENT_OFFSET, 11770 },
+  { 0xfb05, G_UNICODE_NOT_PRESENT_OFFSET, 11774 },
+  { 0xfb06, G_UNICODE_NOT_PRESENT_OFFSET, 11774 },
+  { 0xfb13, G_UNICODE_NOT_PRESENT_OFFSET, 11777 },
+  { 0xfb14, G_UNICODE_NOT_PRESENT_OFFSET, 11782 },
+  { 0xfb15, G_UNICODE_NOT_PRESENT_OFFSET, 11787 },
+  { 0xfb16, G_UNICODE_NOT_PRESENT_OFFSET, 11792 },
+  { 0xfb17, G_UNICODE_NOT_PRESENT_OFFSET, 11797 },
+  { 0xfb1d, 11802, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb1f, 11807, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb20, G_UNICODE_NOT_PRESENT_OFFSET, 11812 },
+  { 0xfb21, G_UNICODE_NOT_PRESENT_OFFSET, 5052 },
+  { 0xfb22, G_UNICODE_NOT_PRESENT_OFFSET, 5061 },
+  { 0xfb23, G_UNICODE_NOT_PRESENT_OFFSET, 11815 },
+  { 0xfb24, G_UNICODE_NOT_PRESENT_OFFSET, 11818 },
+  { 0xfb25, G_UNICODE_NOT_PRESENT_OFFSET, 11821 },
+  { 0xfb26, G_UNICODE_NOT_PRESENT_OFFSET, 11824 },
+  { 0xfb27, G_UNICODE_NOT_PRESENT_OFFSET, 11827 },
+  { 0xfb28, G_UNICODE_NOT_PRESENT_OFFSET, 11830 },
+  { 0xfb29, G_UNICODE_NOT_PRESENT_OFFSET, 4957 },
+  { 0xfb2a, 11833, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb2b, 11838, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb2c, 11843, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb2d, 11850, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb2e, 11857, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb2f, 11862, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb30, 11867, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb31, 11872, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb32, 11877, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb33, 11882, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb34, 11887, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb35, 11892, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb36, 11897, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb38, 11902, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb39, 11907, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb3a, 11912, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb3b, 11917, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb3c, 11922, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb3e, 11927, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb40, 11932, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb41, 11937, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb43, 11942, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb44, 11947, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb46, 11952, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb47, 11957, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb48, 11962, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb49, 11967, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb4a, 11972, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb4b, 11977, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb4c, 11982, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb4d, 11987, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb4e, 11992, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0xfb4f, G_UNICODE_NOT_PRESENT_OFFSET, 11997 },
+  { 0xfb50, G_UNICODE_NOT_PRESENT_OFFSET, 12002 },
+  { 0xfb51, G_UNICODE_NOT_PRESENT_OFFSET, 12002 },
+  { 0xfb52, G_UNICODE_NOT_PRESENT_OFFSET, 12005 },
+  { 0xfb53, G_UNICODE_NOT_PRESENT_OFFSET, 12005 },
+  { 0xfb54, G_UNICODE_NOT_PRESENT_OFFSET, 12005 },
+  { 0xfb55, G_UNICODE_NOT_PRESENT_OFFSET, 12005 },
+  { 0xfb56, G_UNICODE_NOT_PRESENT_OFFSET, 12008 },
+  { 0xfb57, G_UNICODE_NOT_PRESENT_OFFSET, 12008 },
+  { 0xfb58, G_UNICODE_NOT_PRESENT_OFFSET, 12008 },
+  { 0xfb59, G_UNICODE_NOT_PRESENT_OFFSET, 12008 },
+  { 0xfb5a, G_UNICODE_NOT_PRESENT_OFFSET, 12011 },
+  { 0xfb5b, G_UNICODE_NOT_PRESENT_OFFSET, 12011 },
+  { 0xfb5c, G_UNICODE_NOT_PRESENT_OFFSET, 12011 },
+  { 0xfb5d, G_UNICODE_NOT_PRESENT_OFFSET, 12011 },
+  { 0xfb5e, G_UNICODE_NOT_PRESENT_OFFSET, 12014 },
+  { 0xfb5f, G_UNICODE_NOT_PRESENT_OFFSET, 12014 },
+  { 0xfb60, G_UNICODE_NOT_PRESENT_OFFSET, 12014 },
+  { 0xfb61, G_UNICODE_NOT_PRESENT_OFFSET, 12014 },
+  { 0xfb62, G_UNICODE_NOT_PRESENT_OFFSET, 12017 },
+  { 0xfb63, G_UNICODE_NOT_PRESENT_OFFSET, 12017 },
+  { 0xfb64, G_UNICODE_NOT_PRESENT_OFFSET, 12017 },
+  { 0xfb65, G_UNICODE_NOT_PRESENT_OFFSET, 12017 },
+  { 0xfb66, G_UNICODE_NOT_PRESENT_OFFSET, 12020 },
+  { 0xfb67, G_UNICODE_NOT_PRESENT_OFFSET, 12020 },
+  { 0xfb68, G_UNICODE_NOT_PRESENT_OFFSET, 12020 },
+  { 0xfb69, G_UNICODE_NOT_PRESENT_OFFSET, 12020 },
+  { 0xfb6a, G_UNICODE_NOT_PRESENT_OFFSET, 12023 },
+  { 0xfb6b, G_UNICODE_NOT_PRESENT_OFFSET, 12023 },
+  { 0xfb6c, G_UNICODE_NOT_PRESENT_OFFSET, 12023 },
+  { 0xfb6d, G_UNICODE_NOT_PRESENT_OFFSET, 12023 },
+  { 0xfb6e, G_UNICODE_NOT_PRESENT_OFFSET, 12026 },
+  { 0xfb6f, G_UNICODE_NOT_PRESENT_OFFSET, 12026 },
+  { 0xfb70, G_UNICODE_NOT_PRESENT_OFFSET, 12026 },
+  { 0xfb71, G_UNICODE_NOT_PRESENT_OFFSET, 12026 },
+  { 0xfb72, G_UNICODE_NOT_PRESENT_OFFSET, 12029 },
+  { 0xfb73, G_UNICODE_NOT_PRESENT_OFFSET, 12029 },
+  { 0xfb74, G_UNICODE_NOT_PRESENT_OFFSET, 12029 },
+  { 0xfb75, G_UNICODE_NOT_PRESENT_OFFSET, 12029 },
+  { 0xfb76, G_UNICODE_NOT_PRESENT_OFFSET, 12032 },
+  { 0xfb77, G_UNICODE_NOT_PRESENT_OFFSET, 12032 },
+  { 0xfb78, G_UNICODE_NOT_PRESENT_OFFSET, 12032 },
+  { 0xfb79, G_UNICODE_NOT_PRESENT_OFFSET, 12032 },
+  { 0xfb7a, G_UNICODE_NOT_PRESENT_OFFSET, 12035 },
+  { 0xfb7b, G_UNICODE_NOT_PRESENT_OFFSET, 12035 },
+  { 0xfb7c, G_UNICODE_NOT_PRESENT_OFFSET, 12035 },
+  { 0xfb7d, G_UNICODE_NOT_PRESENT_OFFSET, 12035 },
+  { 0xfb7e, G_UNICODE_NOT_PRESENT_OFFSET, 12038 },
+  { 0xfb7f, G_UNICODE_NOT_PRESENT_OFFSET, 12038 },
+  { 0xfb80, G_UNICODE_NOT_PRESENT_OFFSET, 12038 },
+  { 0xfb81, G_UNICODE_NOT_PRESENT_OFFSET, 12038 },
+  { 0xfb82, G_UNICODE_NOT_PRESENT_OFFSET, 12041 },
+  { 0xfb83, G_UNICODE_NOT_PRESENT_OFFSET, 12041 },
+  { 0xfb84, G_UNICODE_NOT_PRESENT_OFFSET, 12044 },
+  { 0xfb85, G_UNICODE_NOT_PRESENT_OFFSET, 12044 },
+  { 0xfb86, G_UNICODE_NOT_PRESENT_OFFSET, 12047 },
+  { 0xfb87, G_UNICODE_NOT_PRESENT_OFFSET, 12047 },
+  { 0xfb88, G_UNICODE_NOT_PRESENT_OFFSET, 12050 },
+  { 0xfb89, G_UNICODE_NOT_PRESENT_OFFSET, 12050 },
+  { 0xfb8a, G_UNICODE_NOT_PRESENT_OFFSET, 12053 },
+  { 0xfb8b, G_UNICODE_NOT_PRESENT_OFFSET, 12053 },
+  { 0xfb8c, G_UNICODE_NOT_PRESENT_OFFSET, 12056 },
+  { 0xfb8d, G_UNICODE_NOT_PRESENT_OFFSET, 12056 },
+  { 0xfb8e, G_UNICODE_NOT_PRESENT_OFFSET, 12059 },
+  { 0xfb8f, G_UNICODE_NOT_PRESENT_OFFSET, 12059 },
+  { 0xfb90, G_UNICODE_NOT_PRESENT_OFFSET, 12059 },
+  { 0xfb91, G_UNICODE_NOT_PRESENT_OFFSET, 12059 },
+  { 0xfb92, G_UNICODE_NOT_PRESENT_OFFSET, 12062 },
+  { 0xfb93, G_UNICODE_NOT_PRESENT_OFFSET, 12062 },
+  { 0xfb94, G_UNICODE_NOT_PRESENT_OFFSET, 12062 },
+  { 0xfb95, G_UNICODE_NOT_PRESENT_OFFSET, 12062 },
+  { 0xfb96, G_UNICODE_NOT_PRESENT_OFFSET, 12065 },
+  { 0xfb97, G_UNICODE_NOT_PRESENT_OFFSET, 12065 },
+  { 0xfb98, G_UNICODE_NOT_PRESENT_OFFSET, 12065 },
+  { 0xfb99, G_UNICODE_NOT_PRESENT_OFFSET, 12065 },
+  { 0xfb9a, G_UNICODE_NOT_PRESENT_OFFSET, 12068 },
+  { 0xfb9b, G_UNICODE_NOT_PRESENT_OFFSET, 12068 },
+  { 0xfb9c, G_UNICODE_NOT_PRESENT_OFFSET, 12068 },
+  { 0xfb9d, G_UNICODE_NOT_PRESENT_OFFSET, 12068 },
+  { 0xfb9e, G_UNICODE_NOT_PRESENT_OFFSET, 12071 },
+  { 0xfb9f, G_UNICODE_NOT_PRESENT_OFFSET, 12071 },
+  { 0xfba0, G_UNICODE_NOT_PRESENT_OFFSET, 12074 },
+  { 0xfba1, G_UNICODE_NOT_PRESENT_OFFSET, 12074 },
+  { 0xfba2, G_UNICODE_NOT_PRESENT_OFFSET, 12074 },
+  { 0xfba3, G_UNICODE_NOT_PRESENT_OFFSET, 12074 },
+  { 0xfba4, G_UNICODE_NOT_PRESENT_OFFSET, 1718 },
+  { 0xfba5, G_UNICODE_NOT_PRESENT_OFFSET, 1718 },
+  { 0xfba6, G_UNICODE_NOT_PRESENT_OFFSET, 12077 },
+  { 0xfba7, G_UNICODE_NOT_PRESENT_OFFSET, 12077 },
+  { 0xfba8, G_UNICODE_NOT_PRESENT_OFFSET, 12077 },
+  { 0xfba9, G_UNICODE_NOT_PRESENT_OFFSET, 12077 },
+  { 0xfbaa, G_UNICODE_NOT_PRESENT_OFFSET, 12080 },
+  { 0xfbab, G_UNICODE_NOT_PRESENT_OFFSET, 12080 },
+  { 0xfbac, G_UNICODE_NOT_PRESENT_OFFSET, 12080 },
+  { 0xfbad, G_UNICODE_NOT_PRESENT_OFFSET, 12080 },
+  { 0xfbae, G_UNICODE_NOT_PRESENT_OFFSET, 12083 },
+  { 0xfbaf, G_UNICODE_NOT_PRESENT_OFFSET, 12083 },
+  { 0xfbb0, G_UNICODE_NOT_PRESENT_OFFSET, 1728 },
+  { 0xfbb1, G_UNICODE_NOT_PRESENT_OFFSET, 1728 },
+  { 0xfbd3, G_UNICODE_NOT_PRESENT_OFFSET, 12086 },
+  { 0xfbd4, G_UNICODE_NOT_PRESENT_OFFSET, 12086 },
+  { 0xfbd5, G_UNICODE_NOT_PRESENT_OFFSET, 12086 },
+  { 0xfbd6, G_UNICODE_NOT_PRESENT_OFFSET, 12086 },
+  { 0xfbd7, G_UNICODE_NOT_PRESENT_OFFSET, 12089 },
+  { 0xfbd8, G_UNICODE_NOT_PRESENT_OFFSET, 12089 },
+  { 0xfbd9, G_UNICODE_NOT_PRESENT_OFFSET, 12092 },
+  { 0xfbda, G_UNICODE_NOT_PRESENT_OFFSET, 12092 },
+  { 0xfbdb, G_UNICODE_NOT_PRESENT_OFFSET, 12095 },
+  { 0xfbdc, G_UNICODE_NOT_PRESENT_OFFSET, 12095 },
+  { 0xfbdd, G_UNICODE_NOT_PRESENT_OFFSET, 1708 },
+  { 0xfbde, G_UNICODE_NOT_PRESENT_OFFSET, 12098 },
+  { 0xfbdf, G_UNICODE_NOT_PRESENT_OFFSET, 12098 },
+  { 0xfbe0, G_UNICODE_NOT_PRESENT_OFFSET, 12101 },
+  { 0xfbe1, G_UNICODE_NOT_PRESENT_OFFSET, 12101 },
+  { 0xfbe2, G_UNICODE_NOT_PRESENT_OFFSET, 12104 },
+  { 0xfbe3, G_UNICODE_NOT_PRESENT_OFFSET, 12104 },
+  { 0xfbe4, G_UNICODE_NOT_PRESENT_OFFSET, 12107 },
+  { 0xfbe5, G_UNICODE_NOT_PRESENT_OFFSET, 12107 },
+  { 0xfbe6, G_UNICODE_NOT_PRESENT_OFFSET, 12107 },
+  { 0xfbe7, G_UNICODE_NOT_PRESENT_OFFSET, 12107 },
+  { 0xfbe8, G_UNICODE_NOT_PRESENT_OFFSET, 12110 },
+  { 0xfbe9, G_UNICODE_NOT_PRESENT_OFFSET, 12110 },
+  { 0xfbea, G_UNICODE_NOT_PRESENT_OFFSET, 12113 },
+  { 0xfbeb, G_UNICODE_NOT_PRESENT_OFFSET, 12113 },
+  { 0xfbec, G_UNICODE_NOT_PRESENT_OFFSET, 12120 },
+  { 0xfbed, G_UNICODE_NOT_PRESENT_OFFSET, 12120 },
+  { 0xfbee, G_UNICODE_NOT_PRESENT_OFFSET, 12127 },
+  { 0xfbef, G_UNICODE_NOT_PRESENT_OFFSET, 12127 },
+  { 0xfbf0, G_UNICODE_NOT_PRESENT_OFFSET, 12134 },
+  { 0xfbf1, G_UNICODE_NOT_PRESENT_OFFSET, 12134 },
+  { 0xfbf2, G_UNICODE_NOT_PRESENT_OFFSET, 12141 },
+  { 0xfbf3, G_UNICODE_NOT_PRESENT_OFFSET, 12141 },
+  { 0xfbf4, G_UNICODE_NOT_PRESENT_OFFSET, 12148 },
+  { 0xfbf5, G_UNICODE_NOT_PRESENT_OFFSET, 12148 },
+  { 0xfbf6, G_UNICODE_NOT_PRESENT_OFFSET, 12155 },
+  { 0xfbf7, G_UNICODE_NOT_PRESENT_OFFSET, 12155 },
+  { 0xfbf8, G_UNICODE_NOT_PRESENT_OFFSET, 12155 },
+  { 0xfbf9, G_UNICODE_NOT_PRESENT_OFFSET, 12162 },
+  { 0xfbfa, G_UNICODE_NOT_PRESENT_OFFSET, 12162 },
+  { 0xfbfb, G_UNICODE_NOT_PRESENT_OFFSET, 12162 },
+  { 0xfbfc, G_UNICODE_NOT_PRESENT_OFFSET, 12169 },
+  { 0xfbfd, G_UNICODE_NOT_PRESENT_OFFSET, 12169 },
+  { 0xfbfe, G_UNICODE_NOT_PRESENT_OFFSET, 12169 },
+  { 0xfbff, G_UNICODE_NOT_PRESENT_OFFSET, 12169 },
+  { 0xfc00, G_UNICODE_NOT_PRESENT_OFFSET, 12172 },
+  { 0xfc01, G_UNICODE_NOT_PRESENT_OFFSET, 12179 },
+  { 0xfc02, G_UNICODE_NOT_PRESENT_OFFSET, 12186 },
+  { 0xfc03, G_UNICODE_NOT_PRESENT_OFFSET, 12162 },
+  { 0xfc04, G_UNICODE_NOT_PRESENT_OFFSET, 12193 },
+  { 0xfc05, G_UNICODE_NOT_PRESENT_OFFSET, 12200 },
+  { 0xfc06, G_UNICODE_NOT_PRESENT_OFFSET, 12205 },
+  { 0xfc07, G_UNICODE_NOT_PRESENT_OFFSET, 12210 },
+  { 0xfc08, G_UNICODE_NOT_PRESENT_OFFSET, 12215 },
+  { 0xfc09, G_UNICODE_NOT_PRESENT_OFFSET, 12220 },
+  { 0xfc0a, G_UNICODE_NOT_PRESENT_OFFSET, 12225 },
+  { 0xfc0b, G_UNICODE_NOT_PRESENT_OFFSET, 12230 },
+  { 0xfc0c, G_UNICODE_NOT_PRESENT_OFFSET, 12235 },
+  { 0xfc0d, G_UNICODE_NOT_PRESENT_OFFSET, 12240 },
+  { 0xfc0e, G_UNICODE_NOT_PRESENT_OFFSET, 12245 },
+  { 0xfc0f, G_UNICODE_NOT_PRESENT_OFFSET, 12250 },
+  { 0xfc10, G_UNICODE_NOT_PRESENT_OFFSET, 12255 },
+  { 0xfc11, G_UNICODE_NOT_PRESENT_OFFSET, 12260 },
+  { 0xfc12, G_UNICODE_NOT_PRESENT_OFFSET, 12265 },
+  { 0xfc13, G_UNICODE_NOT_PRESENT_OFFSET, 12270 },
+  { 0xfc14, G_UNICODE_NOT_PRESENT_OFFSET, 12275 },
+  { 0xfc15, G_UNICODE_NOT_PRESENT_OFFSET, 12280 },
+  { 0xfc16, G_UNICODE_NOT_PRESENT_OFFSET, 12285 },
+  { 0xfc17, G_UNICODE_NOT_PRESENT_OFFSET, 12290 },
+  { 0xfc18, G_UNICODE_NOT_PRESENT_OFFSET, 12295 },
+  { 0xfc19, G_UNICODE_NOT_PRESENT_OFFSET, 12300 },
+  { 0xfc1a, G_UNICODE_NOT_PRESENT_OFFSET, 12305 },
+  { 0xfc1b, G_UNICODE_NOT_PRESENT_OFFSET, 12310 },
+  { 0xfc1c, G_UNICODE_NOT_PRESENT_OFFSET, 12315 },
+  { 0xfc1d, G_UNICODE_NOT_PRESENT_OFFSET, 12320 },
+  { 0xfc1e, G_UNICODE_NOT_PRESENT_OFFSET, 12325 },
+  { 0xfc1f, G_UNICODE_NOT_PRESENT_OFFSET, 12330 },
+  { 0xfc20, G_UNICODE_NOT_PRESENT_OFFSET, 12335 },
+  { 0xfc21, G_UNICODE_NOT_PRESENT_OFFSET, 12340 },
+  { 0xfc22, G_UNICODE_NOT_PRESENT_OFFSET, 12345 },
+  { 0xfc23, G_UNICODE_NOT_PRESENT_OFFSET, 12350 },
+  { 0xfc24, G_UNICODE_NOT_PRESENT_OFFSET, 12355 },
+  { 0xfc25, G_UNICODE_NOT_PRESENT_OFFSET, 12360 },
+  { 0xfc26, G_UNICODE_NOT_PRESENT_OFFSET, 12365 },
+  { 0xfc27, G_UNICODE_NOT_PRESENT_OFFSET, 12370 },
+  { 0xfc28, G_UNICODE_NOT_PRESENT_OFFSET, 12375 },
+  { 0xfc29, G_UNICODE_NOT_PRESENT_OFFSET, 12380 },
+  { 0xfc2a, G_UNICODE_NOT_PRESENT_OFFSET, 12385 },
+  { 0xfc2b, G_UNICODE_NOT_PRESENT_OFFSET, 12390 },
+  { 0xfc2c, G_UNICODE_NOT_PRESENT_OFFSET, 12395 },
+  { 0xfc2d, G_UNICODE_NOT_PRESENT_OFFSET, 12400 },
+  { 0xfc2e, G_UNICODE_NOT_PRESENT_OFFSET, 12405 },
+  { 0xfc2f, G_UNICODE_NOT_PRESENT_OFFSET, 12410 },
+  { 0xfc30, G_UNICODE_NOT_PRESENT_OFFSET, 12415 },
+  { 0xfc31, G_UNICODE_NOT_PRESENT_OFFSET, 12420 },
+  { 0xfc32, G_UNICODE_NOT_PRESENT_OFFSET, 12425 },
+  { 0xfc33, G_UNICODE_NOT_PRESENT_OFFSET, 12430 },
+  { 0xfc34, G_UNICODE_NOT_PRESENT_OFFSET, 12435 },
+  { 0xfc35, G_UNICODE_NOT_PRESENT_OFFSET, 12440 },
+  { 0xfc36, G_UNICODE_NOT_PRESENT_OFFSET, 12445 },
+  { 0xfc37, G_UNICODE_NOT_PRESENT_OFFSET, 12450 },
+  { 0xfc38, G_UNICODE_NOT_PRESENT_OFFSET, 12455 },
+  { 0xfc39, G_UNICODE_NOT_PRESENT_OFFSET, 12460 },
+  { 0xfc3a, G_UNICODE_NOT_PRESENT_OFFSET, 12465 },
+  { 0xfc3b, G_UNICODE_NOT_PRESENT_OFFSET, 12470 },
+  { 0xfc3c, G_UNICODE_NOT_PRESENT_OFFSET, 12475 },
+  { 0xfc3d, G_UNICODE_NOT_PRESENT_OFFSET, 12480 },
+  { 0xfc3e, G_UNICODE_NOT_PRESENT_OFFSET, 12485 },
+  { 0xfc3f, G_UNICODE_NOT_PRESENT_OFFSET, 12490 },
+  { 0xfc40, G_UNICODE_NOT_PRESENT_OFFSET, 12495 },
+  { 0xfc41, G_UNICODE_NOT_PRESENT_OFFSET, 12500 },
+  { 0xfc42, G_UNICODE_NOT_PRESENT_OFFSET, 12505 },
+  { 0xfc43, G_UNICODE_NOT_PRESENT_OFFSET, 12510 },
+  { 0xfc44, G_UNICODE_NOT_PRESENT_OFFSET, 12515 },
+  { 0xfc45, G_UNICODE_NOT_PRESENT_OFFSET, 12520 },
+  { 0xfc46, G_UNICODE_NOT_PRESENT_OFFSET, 12525 },
+  { 0xfc47, G_UNICODE_NOT_PRESENT_OFFSET, 12530 },
+  { 0xfc48, G_UNICODE_NOT_PRESENT_OFFSET, 12535 },
+  { 0xfc49, G_UNICODE_NOT_PRESENT_OFFSET, 12540 },
+  { 0xfc4a, G_UNICODE_NOT_PRESENT_OFFSET, 12545 },
+  { 0xfc4b, G_UNICODE_NOT_PRESENT_OFFSET, 12550 },
+  { 0xfc4c, G_UNICODE_NOT_PRESENT_OFFSET, 12555 },
+  { 0xfc4d, G_UNICODE_NOT_PRESENT_OFFSET, 12560 },
+  { 0xfc4e, G_UNICODE_NOT_PRESENT_OFFSET, 12565 },
+  { 0xfc4f, G_UNICODE_NOT_PRESENT_OFFSET, 12570 },
+  { 0xfc50, G_UNICODE_NOT_PRESENT_OFFSET, 12575 },
+  { 0xfc51, G_UNICODE_NOT_PRESENT_OFFSET, 12580 },
+  { 0xfc52, G_UNICODE_NOT_PRESENT_OFFSET, 12585 },
+  { 0xfc53, G_UNICODE_NOT_PRESENT_OFFSET, 12590 },
+  { 0xfc54, G_UNICODE_NOT_PRESENT_OFFSET, 12595 },
+  { 0xfc55, G_UNICODE_NOT_PRESENT_OFFSET, 12600 },
+  { 0xfc56, G_UNICODE_NOT_PRESENT_OFFSET, 12605 },
+  { 0xfc57, G_UNICODE_NOT_PRESENT_OFFSET, 12610 },
+  { 0xfc58, G_UNICODE_NOT_PRESENT_OFFSET, 12615 },
+  { 0xfc59, G_UNICODE_NOT_PRESENT_OFFSET, 12620 },
+  { 0xfc5a, G_UNICODE_NOT_PRESENT_OFFSET, 12625 },
+  { 0xfc5b, G_UNICODE_NOT_PRESENT_OFFSET, 12630 },
+  { 0xfc5c, G_UNICODE_NOT_PRESENT_OFFSET, 12635 },
+  { 0xfc5d, G_UNICODE_NOT_PRESENT_OFFSET, 12640 },
+  { 0xfc5e, G_UNICODE_NOT_PRESENT_OFFSET, 12645 },
+  { 0xfc5f, G_UNICODE_NOT_PRESENT_OFFSET, 12651 },
+  { 0xfc60, G_UNICODE_NOT_PRESENT_OFFSET, 12657 },
+  { 0xfc61, G_UNICODE_NOT_PRESENT_OFFSET, 12663 },
+  { 0xfc62, G_UNICODE_NOT_PRESENT_OFFSET, 12669 },
+  { 0xfc63, G_UNICODE_NOT_PRESENT_OFFSET, 12675 },
+  { 0xfc64, G_UNICODE_NOT_PRESENT_OFFSET, 12681 },
+  { 0xfc65, G_UNICODE_NOT_PRESENT_OFFSET, 12688 },
+  { 0xfc66, G_UNICODE_NOT_PRESENT_OFFSET, 12186 },
+  { 0xfc67, G_UNICODE_NOT_PRESENT_OFFSET, 12695 },
+  { 0xfc68, G_UNICODE_NOT_PRESENT_OFFSET, 12162 },
+  { 0xfc69, G_UNICODE_NOT_PRESENT_OFFSET, 12193 },
+  { 0xfc6a, G_UNICODE_NOT_PRESENT_OFFSET, 12702 },
+  { 0xfc6b, G_UNICODE_NOT_PRESENT_OFFSET, 12707 },
+  { 0xfc6c, G_UNICODE_NOT_PRESENT_OFFSET, 12215 },
+  { 0xfc6d, G_UNICODE_NOT_PRESENT_OFFSET, 12712 },
+  { 0xfc6e, G_UNICODE_NOT_PRESENT_OFFSET, 12220 },
+  { 0xfc6f, G_UNICODE_NOT_PRESENT_OFFSET, 12225 },
+  { 0xfc70, G_UNICODE_NOT_PRESENT_OFFSET, 12717 },
+  { 0xfc71, G_UNICODE_NOT_PRESENT_OFFSET, 12722 },
+  { 0xfc72, G_UNICODE_NOT_PRESENT_OFFSET, 12245 },
+  { 0xfc73, G_UNICODE_NOT_PRESENT_OFFSET, 12727 },
+  { 0xfc74, G_UNICODE_NOT_PRESENT_OFFSET, 12250 },
+  { 0xfc75, G_UNICODE_NOT_PRESENT_OFFSET, 12255 },
+  { 0xfc76, G_UNICODE_NOT_PRESENT_OFFSET, 12732 },
+  { 0xfc77, G_UNICODE_NOT_PRESENT_OFFSET, 12737 },
+  { 0xfc78, G_UNICODE_NOT_PRESENT_OFFSET, 12265 },
+  { 0xfc79, G_UNICODE_NOT_PRESENT_OFFSET, 12742 },
+  { 0xfc7a, G_UNICODE_NOT_PRESENT_OFFSET, 12270 },
+  { 0xfc7b, G_UNICODE_NOT_PRESENT_OFFSET, 12275 },
+  { 0xfc7c, G_UNICODE_NOT_PRESENT_OFFSET, 12420 },
+  { 0xfc7d, G_UNICODE_NOT_PRESENT_OFFSET, 12425 },
+  { 0xfc7e, G_UNICODE_NOT_PRESENT_OFFSET, 12440 },
+  { 0xfc7f, G_UNICODE_NOT_PRESENT_OFFSET, 12445 },
+  { 0xfc80, G_UNICODE_NOT_PRESENT_OFFSET, 12450 },
+  { 0xfc81, G_UNICODE_NOT_PRESENT_OFFSET, 12470 },
+  { 0xfc82, G_UNICODE_NOT_PRESENT_OFFSET, 12475 },
+  { 0xfc83, G_UNICODE_NOT_PRESENT_OFFSET, 12480 },
+  { 0xfc84, G_UNICODE_NOT_PRESENT_OFFSET, 12485 },
+  { 0xfc85, G_UNICODE_NOT_PRESENT_OFFSET, 12505 },
+  { 0xfc86, G_UNICODE_NOT_PRESENT_OFFSET, 12510 },
+  { 0xfc87, G_UNICODE_NOT_PRESENT_OFFSET, 12515 },
+  { 0xfc88, G_UNICODE_NOT_PRESENT_OFFSET, 12747 },
+  { 0xfc89, G_UNICODE_NOT_PRESENT_OFFSET, 12535 },
+  { 0xfc8a, G_UNICODE_NOT_PRESENT_OFFSET, 12752 },
+  { 0xfc8b, G_UNICODE_NOT_PRESENT_OFFSET, 12757 },
+  { 0xfc8c, G_UNICODE_NOT_PRESENT_OFFSET, 12565 },
+  { 0xfc8d, G_UNICODE_NOT_PRESENT_OFFSET, 12762 },
+  { 0xfc8e, G_UNICODE_NOT_PRESENT_OFFSET, 12570 },
+  { 0xfc8f, G_UNICODE_NOT_PRESENT_OFFSET, 12575 },
+  { 0xfc90, G_UNICODE_NOT_PRESENT_OFFSET, 12640 },
+  { 0xfc91, G_UNICODE_NOT_PRESENT_OFFSET, 12767 },
+  { 0xfc92, G_UNICODE_NOT_PRESENT_OFFSET, 12772 },
+  { 0xfc93, G_UNICODE_NOT_PRESENT_OFFSET, 12615 },
+  { 0xfc94, G_UNICODE_NOT_PRESENT_OFFSET, 12777 },
+  { 0xfc95, G_UNICODE_NOT_PRESENT_OFFSET, 12620 },
+  { 0xfc96, G_UNICODE_NOT_PRESENT_OFFSET, 12625 },
+  { 0xfc97, G_UNICODE_NOT_PRESENT_OFFSET, 12172 },
+  { 0xfc98, G_UNICODE_NOT_PRESENT_OFFSET, 12179 },
+  { 0xfc99, G_UNICODE_NOT_PRESENT_OFFSET, 12782 },
+  { 0xfc9a, G_UNICODE_NOT_PRESENT_OFFSET, 12186 },
+  { 0xfc9b, G_UNICODE_NOT_PRESENT_OFFSET, 12789 },
+  { 0xfc9c, G_UNICODE_NOT_PRESENT_OFFSET, 12200 },
+  { 0xfc9d, G_UNICODE_NOT_PRESENT_OFFSET, 12205 },
+  { 0xfc9e, G_UNICODE_NOT_PRESENT_OFFSET, 12210 },
+  { 0xfc9f, G_UNICODE_NOT_PRESENT_OFFSET, 12215 },
+  { 0xfca0, G_UNICODE_NOT_PRESENT_OFFSET, 12796 },
+  { 0xfca1, G_UNICODE_NOT_PRESENT_OFFSET, 12230 },
+  { 0xfca2, G_UNICODE_NOT_PRESENT_OFFSET, 12235 },
+  { 0xfca3, G_UNICODE_NOT_PRESENT_OFFSET, 12240 },
+  { 0xfca4, G_UNICODE_NOT_PRESENT_OFFSET, 12245 },
+  { 0xfca5, G_UNICODE_NOT_PRESENT_OFFSET, 12801 },
+  { 0xfca6, G_UNICODE_NOT_PRESENT_OFFSET, 12265 },
+  { 0xfca7, G_UNICODE_NOT_PRESENT_OFFSET, 12280 },
+  { 0xfca8, G_UNICODE_NOT_PRESENT_OFFSET, 12285 },
+  { 0xfca9, G_UNICODE_NOT_PRESENT_OFFSET, 12290 },
+  { 0xfcaa, G_UNICODE_NOT_PRESENT_OFFSET, 12295 },
+  { 0xfcab, G_UNICODE_NOT_PRESENT_OFFSET, 12300 },
+  { 0xfcac, G_UNICODE_NOT_PRESENT_OFFSET, 12310 },
+  { 0xfcad, G_UNICODE_NOT_PRESENT_OFFSET, 12315 },
+  { 0xfcae, G_UNICODE_NOT_PRESENT_OFFSET, 12320 },
+  { 0xfcaf, G_UNICODE_NOT_PRESENT_OFFSET, 12325 },
+  { 0xfcb0, G_UNICODE_NOT_PRESENT_OFFSET, 12330 },
+  { 0xfcb1, G_UNICODE_NOT_PRESENT_OFFSET, 12335 },
+  { 0xfcb2, G_UNICODE_NOT_PRESENT_OFFSET, 12806 },
+  { 0xfcb3, G_UNICODE_NOT_PRESENT_OFFSET, 12340 },
+  { 0xfcb4, G_UNICODE_NOT_PRESENT_OFFSET, 12345 },
+  { 0xfcb5, G_UNICODE_NOT_PRESENT_OFFSET, 12350 },
+  { 0xfcb6, G_UNICODE_NOT_PRESENT_OFFSET, 12355 },
+  { 0xfcb7, G_UNICODE_NOT_PRESENT_OFFSET, 12360 },
+  { 0xfcb8, G_UNICODE_NOT_PRESENT_OFFSET, 12365 },
+  { 0xfcb9, G_UNICODE_NOT_PRESENT_OFFSET, 12375 },
+  { 0xfcba, G_UNICODE_NOT_PRESENT_OFFSET, 12380 },
+  { 0xfcbb, G_UNICODE_NOT_PRESENT_OFFSET, 12385 },
+  { 0xfcbc, G_UNICODE_NOT_PRESENT_OFFSET, 12390 },
+  { 0xfcbd, G_UNICODE_NOT_PRESENT_OFFSET, 12395 },
+  { 0xfcbe, G_UNICODE_NOT_PRESENT_OFFSET, 12400 },
+  { 0xfcbf, G_UNICODE_NOT_PRESENT_OFFSET, 12405 },
+  { 0xfcc0, G_UNICODE_NOT_PRESENT_OFFSET, 12410 },
+  { 0xfcc1, G_UNICODE_NOT_PRESENT_OFFSET, 12415 },
+  { 0xfcc2, G_UNICODE_NOT_PRESENT_OFFSET, 12430 },
+  { 0xfcc3, G_UNICODE_NOT_PRESENT_OFFSET, 12435 },
+  { 0xfcc4, G_UNICODE_NOT_PRESENT_OFFSET, 12455 },
+  { 0xfcc5, G_UNICODE_NOT_PRESENT_OFFSET, 12460 },
+  { 0xfcc6, G_UNICODE_NOT_PRESENT_OFFSET, 12465 },
+  { 0xfcc7, G_UNICODE_NOT_PRESENT_OFFSET, 12470 },
+  { 0xfcc8, G_UNICODE_NOT_PRESENT_OFFSET, 12475 },
+  { 0xfcc9, G_UNICODE_NOT_PRESENT_OFFSET, 12490 },
+  { 0xfcca, G_UNICODE_NOT_PRESENT_OFFSET, 12495 },
+  { 0xfccb, G_UNICODE_NOT_PRESENT_OFFSET, 12500 },
+  { 0xfccc, G_UNICODE_NOT_PRESENT_OFFSET, 12505 },
+  { 0xfccd, G_UNICODE_NOT_PRESENT_OFFSET, 12811 },
+  { 0xfcce, G_UNICODE_NOT_PRESENT_OFFSET, 12520 },
+  { 0xfccf, G_UNICODE_NOT_PRESENT_OFFSET, 12525 },
+  { 0xfcd0, G_UNICODE_NOT_PRESENT_OFFSET, 12530 },
+  { 0xfcd1, G_UNICODE_NOT_PRESENT_OFFSET, 12535 },
+  { 0xfcd2, G_UNICODE_NOT_PRESENT_OFFSET, 12550 },
+  { 0xfcd3, G_UNICODE_NOT_PRESENT_OFFSET, 12555 },
+  { 0xfcd4, G_UNICODE_NOT_PRESENT_OFFSET, 12560 },
+  { 0xfcd5, G_UNICODE_NOT_PRESENT_OFFSET, 12565 },
+  { 0xfcd6, G_UNICODE_NOT_PRESENT_OFFSET, 12816 },
+  { 0xfcd7, G_UNICODE_NOT_PRESENT_OFFSET, 12580 },
+  { 0xfcd8, G_UNICODE_NOT_PRESENT_OFFSET, 12585 },
+  { 0xfcd9, G_UNICODE_NOT_PRESENT_OFFSET, 12821 },
+  { 0xfcda, G_UNICODE_NOT_PRESENT_OFFSET, 12600 },
+  { 0xfcdb, G_UNICODE_NOT_PRESENT_OFFSET, 12605 },
+  { 0xfcdc, G_UNICODE_NOT_PRESENT_OFFSET, 12610 },
+  { 0xfcdd, G_UNICODE_NOT_PRESENT_OFFSET, 12615 },
+  { 0xfcde, G_UNICODE_NOT_PRESENT_OFFSET, 12826 },
+  { 0xfcdf, G_UNICODE_NOT_PRESENT_OFFSET, 12186 },
+  { 0xfce0, G_UNICODE_NOT_PRESENT_OFFSET, 12789 },
+  { 0xfce1, G_UNICODE_NOT_PRESENT_OFFSET, 12215 },
+  { 0xfce2, G_UNICODE_NOT_PRESENT_OFFSET, 12796 },
+  { 0xfce3, G_UNICODE_NOT_PRESENT_OFFSET, 12245 },
+  { 0xfce4, G_UNICODE_NOT_PRESENT_OFFSET, 12801 },
+  { 0xfce5, G_UNICODE_NOT_PRESENT_OFFSET, 12265 },
+  { 0xfce6, G_UNICODE_NOT_PRESENT_OFFSET, 12831 },
+  { 0xfce7, G_UNICODE_NOT_PRESENT_OFFSET, 12330 },
+  { 0xfce8, G_UNICODE_NOT_PRESENT_OFFSET, 12836 },
+  { 0xfce9, G_UNICODE_NOT_PRESENT_OFFSET, 12841 },
+  { 0xfcea, G_UNICODE_NOT_PRESENT_OFFSET, 12846 },
+  { 0xfceb, G_UNICODE_NOT_PRESENT_OFFSET, 12470 },
+  { 0xfcec, G_UNICODE_NOT_PRESENT_OFFSET, 12475 },
+  { 0xfced, G_UNICODE_NOT_PRESENT_OFFSET, 12505 },
+  { 0xfcee, G_UNICODE_NOT_PRESENT_OFFSET, 12565 },
+  { 0xfcef, G_UNICODE_NOT_PRESENT_OFFSET, 12816 },
+  { 0xfcf0, G_UNICODE_NOT_PRESENT_OFFSET, 12615 },
+  { 0xfcf1, G_UNICODE_NOT_PRESENT_OFFSET, 12826 },
+  { 0xfcf2, G_UNICODE_NOT_PRESENT_OFFSET, 12851 },
+  { 0xfcf3, G_UNICODE_NOT_PRESENT_OFFSET, 12858 },
+  { 0xfcf4, G_UNICODE_NOT_PRESENT_OFFSET, 12865 },
+  { 0xfcf5, G_UNICODE_NOT_PRESENT_OFFSET, 12872 },
+  { 0xfcf6, G_UNICODE_NOT_PRESENT_OFFSET, 12877 },
+  { 0xfcf7, G_UNICODE_NOT_PRESENT_OFFSET, 12882 },
+  { 0xfcf8, G_UNICODE_NOT_PRESENT_OFFSET, 12887 },
+  { 0xfcf9, G_UNICODE_NOT_PRESENT_OFFSET, 12892 },
+  { 0xfcfa, G_UNICODE_NOT_PRESENT_OFFSET, 12897 },
+  { 0xfcfb, G_UNICODE_NOT_PRESENT_OFFSET, 12902 },
+  { 0xfcfc, G_UNICODE_NOT_PRESENT_OFFSET, 12907 },
+  { 0xfcfd, G_UNICODE_NOT_PRESENT_OFFSET, 12912 },
+  { 0xfcfe, G_UNICODE_NOT_PRESENT_OFFSET, 12917 },
+  { 0xfcff, G_UNICODE_NOT_PRESENT_OFFSET, 12922 },
+  { 0xfd00, G_UNICODE_NOT_PRESENT_OFFSET, 12927 },
+  { 0xfd01, G_UNICODE_NOT_PRESENT_OFFSET, 12932 },
+  { 0xfd02, G_UNICODE_NOT_PRESENT_OFFSET, 12937 },
+  { 0xfd03, G_UNICODE_NOT_PRESENT_OFFSET, 12942 },
+  { 0xfd04, G_UNICODE_NOT_PRESENT_OFFSET, 12947 },
+  { 0xfd05, G_UNICODE_NOT_PRESENT_OFFSET, 12952 },
+  { 0xfd06, G_UNICODE_NOT_PRESENT_OFFSET, 12957 },
+  { 0xfd07, G_UNICODE_NOT_PRESENT_OFFSET, 12962 },
+  { 0xfd08, G_UNICODE_NOT_PRESENT_OFFSET, 12967 },
+  { 0xfd09, G_UNICODE_NOT_PRESENT_OFFSET, 12972 },
+  { 0xfd0a, G_UNICODE_NOT_PRESENT_OFFSET, 12977 },
+  { 0xfd0b, G_UNICODE_NOT_PRESENT_OFFSET, 12982 },
+  { 0xfd0c, G_UNICODE_NOT_PRESENT_OFFSET, 12841 },
+  { 0xfd0d, G_UNICODE_NOT_PRESENT_OFFSET, 12987 },
+  { 0xfd0e, G_UNICODE_NOT_PRESENT_OFFSET, 12992 },
+  { 0xfd0f, G_UNICODE_NOT_PRESENT_OFFSET, 12997 },
+  { 0xfd10, G_UNICODE_NOT_PRESENT_OFFSET, 13002 },
+  { 0xfd11, G_UNICODE_NOT_PRESENT_OFFSET, 12872 },
+  { 0xfd12, G_UNICODE_NOT_PRESENT_OFFSET, 12877 },
+  { 0xfd13, G_UNICODE_NOT_PRESENT_OFFSET, 12882 },
+  { 0xfd14, G_UNICODE_NOT_PRESENT_OFFSET, 12887 },
+  { 0xfd15, G_UNICODE_NOT_PRESENT_OFFSET, 12892 },
+  { 0xfd16, G_UNICODE_NOT_PRESENT_OFFSET, 12897 },
+  { 0xfd17, G_UNICODE_NOT_PRESENT_OFFSET, 12902 },
+  { 0xfd18, G_UNICODE_NOT_PRESENT_OFFSET, 12907 },
+  { 0xfd19, G_UNICODE_NOT_PRESENT_OFFSET, 12912 },
+  { 0xfd1a, G_UNICODE_NOT_PRESENT_OFFSET, 12917 },
+  { 0xfd1b, G_UNICODE_NOT_PRESENT_OFFSET, 12922 },
+  { 0xfd1c, G_UNICODE_NOT_PRESENT_OFFSET, 12927 },
+  { 0xfd1d, G_UNICODE_NOT_PRESENT_OFFSET, 12932 },
+  { 0xfd1e, G_UNICODE_NOT_PRESENT_OFFSET, 12937 },
+  { 0xfd1f, G_UNICODE_NOT_PRESENT_OFFSET, 12942 },
+  { 0xfd20, G_UNICODE_NOT_PRESENT_OFFSET, 12947 },
+  { 0xfd21, G_UNICODE_NOT_PRESENT_OFFSET, 12952 },
+  { 0xfd22, G_UNICODE_NOT_PRESENT_OFFSET, 12957 },
+  { 0xfd23, G_UNICODE_NOT_PRESENT_OFFSET, 12962 },
+  { 0xfd24, G_UNICODE_NOT_PRESENT_OFFSET, 12967 },
+  { 0xfd25, G_UNICODE_NOT_PRESENT_OFFSET, 12972 },
+  { 0xfd26, G_UNICODE_NOT_PRESENT_OFFSET, 12977 },
+  { 0xfd27, G_UNICODE_NOT_PRESENT_OFFSET, 12982 },
+  { 0xfd28, G_UNICODE_NOT_PRESENT_OFFSET, 12841 },
+  { 0xfd29, G_UNICODE_NOT_PRESENT_OFFSET, 12987 },
+  { 0xfd2a, G_UNICODE_NOT_PRESENT_OFFSET, 12992 },
+  { 0xfd2b, G_UNICODE_NOT_PRESENT_OFFSET, 12997 },
+  { 0xfd2c, G_UNICODE_NOT_PRESENT_OFFSET, 13002 },
+  { 0xfd2d, G_UNICODE_NOT_PRESENT_OFFSET, 12972 },
+  { 0xfd2e, G_UNICODE_NOT_PRESENT_OFFSET, 12977 },
+  { 0xfd2f, G_UNICODE_NOT_PRESENT_OFFSET, 12982 },
+  { 0xfd30, G_UNICODE_NOT_PRESENT_OFFSET, 12841 },
+  { 0xfd31, G_UNICODE_NOT_PRESENT_OFFSET, 12836 },
+  { 0xfd32, G_UNICODE_NOT_PRESENT_OFFSET, 12846 },
+  { 0xfd33, G_UNICODE_NOT_PRESENT_OFFSET, 12370 },
+  { 0xfd34, G_UNICODE_NOT_PRESENT_OFFSET, 12315 },
+  { 0xfd35, G_UNICODE_NOT_PRESENT_OFFSET, 12320 },
+  { 0xfd36, G_UNICODE_NOT_PRESENT_OFFSET, 12325 },
+  { 0xfd37, G_UNICODE_NOT_PRESENT_OFFSET, 12972 },
+  { 0xfd38, G_UNICODE_NOT_PRESENT_OFFSET, 12977 },
+  { 0xfd39, G_UNICODE_NOT_PRESENT_OFFSET, 12982 },
+  { 0xfd3a, G_UNICODE_NOT_PRESENT_OFFSET, 12370 },
+  { 0xfd3b, G_UNICODE_NOT_PRESENT_OFFSET, 12375 },
+  { 0xfd3c, G_UNICODE_NOT_PRESENT_OFFSET, 13007 },
+  { 0xfd3d, G_UNICODE_NOT_PRESENT_OFFSET, 13007 },
+  { 0xfd50, G_UNICODE_NOT_PRESENT_OFFSET, 13012 },
+  { 0xfd51, G_UNICODE_NOT_PRESENT_OFFSET, 13019 },
+  { 0xfd52, G_UNICODE_NOT_PRESENT_OFFSET, 13019 },
+  { 0xfd53, G_UNICODE_NOT_PRESENT_OFFSET, 13026 },
+  { 0xfd54, G_UNICODE_NOT_PRESENT_OFFSET, 13033 },
+  { 0xfd55, G_UNICODE_NOT_PRESENT_OFFSET, 13040 },
+  { 0xfd56, G_UNICODE_NOT_PRESENT_OFFSET, 13047 },
+  { 0xfd57, G_UNICODE_NOT_PRESENT_OFFSET, 13054 },
+  { 0xfd58, G_UNICODE_NOT_PRESENT_OFFSET, 13061 },
+  { 0xfd59, G_UNICODE_NOT_PRESENT_OFFSET, 13061 },
+  { 0xfd5a, G_UNICODE_NOT_PRESENT_OFFSET, 13068 },
+  { 0xfd5b, G_UNICODE_NOT_PRESENT_OFFSET, 13075 },
+  { 0xfd5c, G_UNICODE_NOT_PRESENT_OFFSET, 13082 },
+  { 0xfd5d, G_UNICODE_NOT_PRESENT_OFFSET, 13089 },
+  { 0xfd5e, G_UNICODE_NOT_PRESENT_OFFSET, 13096 },
+  { 0xfd5f, G_UNICODE_NOT_PRESENT_OFFSET, 13103 },
+  { 0xfd60, G_UNICODE_NOT_PRESENT_OFFSET, 13103 },
+  { 0xfd61, G_UNICODE_NOT_PRESENT_OFFSET, 13110 },
+  { 0xfd62, G_UNICODE_NOT_PRESENT_OFFSET, 13117 },
+  { 0xfd63, G_UNICODE_NOT_PRESENT_OFFSET, 13117 },
+  { 0xfd64, G_UNICODE_NOT_PRESENT_OFFSET, 13124 },
+  { 0xfd65, G_UNICODE_NOT_PRESENT_OFFSET, 13124 },
+  { 0xfd66, G_UNICODE_NOT_PRESENT_OFFSET, 13131 },
+  { 0xfd67, G_UNICODE_NOT_PRESENT_OFFSET, 13138 },
+  { 0xfd68, G_UNICODE_NOT_PRESENT_OFFSET, 13138 },
+  { 0xfd69, G_UNICODE_NOT_PRESENT_OFFSET, 13145 },
+  { 0xfd6a, G_UNICODE_NOT_PRESENT_OFFSET, 13152 },
+  { 0xfd6b, G_UNICODE_NOT_PRESENT_OFFSET, 13152 },
+  { 0xfd6c, G_UNICODE_NOT_PRESENT_OFFSET, 13159 },
+  { 0xfd6d, G_UNICODE_NOT_PRESENT_OFFSET, 13159 },
+  { 0xfd6e, G_UNICODE_NOT_PRESENT_OFFSET, 13166 },
+  { 0xfd6f, G_UNICODE_NOT_PRESENT_OFFSET, 13173 },
+  { 0xfd70, G_UNICODE_NOT_PRESENT_OFFSET, 13173 },
+  { 0xfd71, G_UNICODE_NOT_PRESENT_OFFSET, 13180 },
+  { 0xfd72, G_UNICODE_NOT_PRESENT_OFFSET, 13180 },
+  { 0xfd73, G_UNICODE_NOT_PRESENT_OFFSET, 13187 },
+  { 0xfd74, G_UNICODE_NOT_PRESENT_OFFSET, 13194 },
+  { 0xfd75, G_UNICODE_NOT_PRESENT_OFFSET, 13201 },
+  { 0xfd76, G_UNICODE_NOT_PRESENT_OFFSET, 13208 },
+  { 0xfd77, G_UNICODE_NOT_PRESENT_OFFSET, 13208 },
+  { 0xfd78, G_UNICODE_NOT_PRESENT_OFFSET, 13215 },
+  { 0xfd79, G_UNICODE_NOT_PRESENT_OFFSET, 13222 },
+  { 0xfd7a, G_UNICODE_NOT_PRESENT_OFFSET, 13229 },
+  { 0xfd7b, G_UNICODE_NOT_PRESENT_OFFSET, 13236 },
+  { 0xfd7c, G_UNICODE_NOT_PRESENT_OFFSET, 13243 },
+  { 0xfd7d, G_UNICODE_NOT_PRESENT_OFFSET, 13243 },
+  { 0xfd7e, G_UNICODE_NOT_PRESENT_OFFSET, 13250 },
+  { 0xfd7f, G_UNICODE_NOT_PRESENT_OFFSET, 13257 },
+  { 0xfd80, G_UNICODE_NOT_PRESENT_OFFSET, 13264 },
+  { 0xfd81, G_UNICODE_NOT_PRESENT_OFFSET, 13271 },
+  { 0xfd82, G_UNICODE_NOT_PRESENT_OFFSET, 13278 },
+  { 0xfd83, G_UNICODE_NOT_PRESENT_OFFSET, 13285 },
+  { 0xfd84, G_UNICODE_NOT_PRESENT_OFFSET, 13285 },
+  { 0xfd85, G_UNICODE_NOT_PRESENT_OFFSET, 13292 },
+  { 0xfd86, G_UNICODE_NOT_PRESENT_OFFSET, 13292 },
+  { 0xfd87, G_UNICODE_NOT_PRESENT_OFFSET, 13299 },
+  { 0xfd88, G_UNICODE_NOT_PRESENT_OFFSET, 13299 },
+  { 0xfd89, G_UNICODE_NOT_PRESENT_OFFSET, 13306 },
+  { 0xfd8a, G_UNICODE_NOT_PRESENT_OFFSET, 13313 },
+  { 0xfd8b, G_UNICODE_NOT_PRESENT_OFFSET, 13320 },
+  { 0xfd8c, G_UNICODE_NOT_PRESENT_OFFSET, 13327 },
+  { 0xfd8d, G_UNICODE_NOT_PRESENT_OFFSET, 13334 },
+  { 0xfd8e, G_UNICODE_NOT_PRESENT_OFFSET, 13341 },
+  { 0xfd8f, G_UNICODE_NOT_PRESENT_OFFSET, 13348 },
+  { 0xfd92, G_UNICODE_NOT_PRESENT_OFFSET, 13355 },
+  { 0xfd93, G_UNICODE_NOT_PRESENT_OFFSET, 13362 },
+  { 0xfd94, G_UNICODE_NOT_PRESENT_OFFSET, 13369 },
+  { 0xfd95, G_UNICODE_NOT_PRESENT_OFFSET, 13376 },
+  { 0xfd96, G_UNICODE_NOT_PRESENT_OFFSET, 13383 },
+  { 0xfd97, G_UNICODE_NOT_PRESENT_OFFSET, 13390 },
+  { 0xfd98, G_UNICODE_NOT_PRESENT_OFFSET, 13390 },
+  { 0xfd99, G_UNICODE_NOT_PRESENT_OFFSET, 13397 },
+  { 0xfd9a, G_UNICODE_NOT_PRESENT_OFFSET, 13404 },
+  { 0xfd9b, G_UNICODE_NOT_PRESENT_OFFSET, 13411 },
+  { 0xfd9c, G_UNICODE_NOT_PRESENT_OFFSET, 13418 },
+  { 0xfd9d, G_UNICODE_NOT_PRESENT_OFFSET, 13418 },
+  { 0xfd9e, G_UNICODE_NOT_PRESENT_OFFSET, 13425 },
+  { 0xfd9f, G_UNICODE_NOT_PRESENT_OFFSET, 13432 },
+  { 0xfda0, G_UNICODE_NOT_PRESENT_OFFSET, 13439 },
+  { 0xfda1, G_UNICODE_NOT_PRESENT_OFFSET, 13446 },
+  { 0xfda2, G_UNICODE_NOT_PRESENT_OFFSET, 13453 },
+  { 0xfda3, G_UNICODE_NOT_PRESENT_OFFSET, 13460 },
+  { 0xfda4, G_UNICODE_NOT_PRESENT_OFFSET, 13467 },
+  { 0xfda5, G_UNICODE_NOT_PRESENT_OFFSET, 13474 },
+  { 0xfda6, G_UNICODE_NOT_PRESENT_OFFSET, 13481 },
+  { 0xfda7, G_UNICODE_NOT_PRESENT_OFFSET, 13488 },
+  { 0xfda8, G_UNICODE_NOT_PRESENT_OFFSET, 13495 },
+  { 0xfda9, G_UNICODE_NOT_PRESENT_OFFSET, 13502 },
+  { 0xfdaa, G_UNICODE_NOT_PRESENT_OFFSET, 13509 },
+  { 0xfdab, G_UNICODE_NOT_PRESENT_OFFSET, 13516 },
+  { 0xfdac, G_UNICODE_NOT_PRESENT_OFFSET, 13523 },
+  { 0xfdad, G_UNICODE_NOT_PRESENT_OFFSET, 13530 },
+  { 0xfdae, G_UNICODE_NOT_PRESENT_OFFSET, 13537 },
+  { 0xfdaf, G_UNICODE_NOT_PRESENT_OFFSET, 13544 },
+  { 0xfdb0, G_UNICODE_NOT_PRESENT_OFFSET, 13551 },
+  { 0xfdb1, G_UNICODE_NOT_PRESENT_OFFSET, 13558 },
+  { 0xfdb2, G_UNICODE_NOT_PRESENT_OFFSET, 13565 },
+  { 0xfdb3, G_UNICODE_NOT_PRESENT_OFFSET, 13572 },
+  { 0xfdb4, G_UNICODE_NOT_PRESENT_OFFSET, 13250 },
+  { 0xfdb5, G_UNICODE_NOT_PRESENT_OFFSET, 13264 },
+  { 0xfdb6, G_UNICODE_NOT_PRESENT_OFFSET, 13579 },
+  { 0xfdb7, G_UNICODE_NOT_PRESENT_OFFSET, 13586 },
+  { 0xfdb8, G_UNICODE_NOT_PRESENT_OFFSET, 13593 },
+  { 0xfdb9, G_UNICODE_NOT_PRESENT_OFFSET, 13600 },
+  { 0xfdba, G_UNICODE_NOT_PRESENT_OFFSET, 13607 },
+  { 0xfdbb, G_UNICODE_NOT_PRESENT_OFFSET, 13614 },
+  { 0xfdbc, G_UNICODE_NOT_PRESENT_OFFSET, 13607 },
+  { 0xfdbd, G_UNICODE_NOT_PRESENT_OFFSET, 13593 },
+  { 0xfdbe, G_UNICODE_NOT_PRESENT_OFFSET, 13621 },
+  { 0xfdbf, G_UNICODE_NOT_PRESENT_OFFSET, 13628 },
+  { 0xfdc0, G_UNICODE_NOT_PRESENT_OFFSET, 13635 },
+  { 0xfdc1, G_UNICODE_NOT_PRESENT_OFFSET, 13642 },
+  { 0xfdc2, G_UNICODE_NOT_PRESENT_OFFSET, 13649 },
+  { 0xfdc3, G_UNICODE_NOT_PRESENT_OFFSET, 13614 },
+  { 0xfdc4, G_UNICODE_NOT_PRESENT_OFFSET, 13201 },
+  { 0xfdc5, G_UNICODE_NOT_PRESENT_OFFSET, 13131 },
+  { 0xfdc6, G_UNICODE_NOT_PRESENT_OFFSET, 13656 },
+  { 0xfdc7, G_UNICODE_NOT_PRESENT_OFFSET, 13663 },
+  { 0xfdf0, G_UNICODE_NOT_PRESENT_OFFSET, 13670 },
+  { 0xfdf1, G_UNICODE_NOT_PRESENT_OFFSET, 13677 },
+  { 0xfdf2, G_UNICODE_NOT_PRESENT_OFFSET, 13684 },
+  { 0xfdf3, G_UNICODE_NOT_PRESENT_OFFSET, 13693 },
+  { 0xfdf4, G_UNICODE_NOT_PRESENT_OFFSET, 13702 },
+  { 0xfdf5, G_UNICODE_NOT_PRESENT_OFFSET, 13711 },
+  { 0xfdf6, G_UNICODE_NOT_PRESENT_OFFSET, 13720 },
+  { 0xfdf7, G_UNICODE_NOT_PRESENT_OFFSET, 13729 },
+  { 0xfdf8, G_UNICODE_NOT_PRESENT_OFFSET, 13738 },
+  { 0xfdf9, G_UNICODE_NOT_PRESENT_OFFSET, 13747 },
+  { 0xfdfa, G_UNICODE_NOT_PRESENT_OFFSET, 13754 },
+  { 0xfdfb, G_UNICODE_NOT_PRESENT_OFFSET, 13788 },
+  { 0xfdfc, G_UNICODE_NOT_PRESENT_OFFSET, 13804 },
+  { 0xfe30, G_UNICODE_NOT_PRESENT_OFFSET, 4871 },
+  { 0xfe31, G_UNICODE_NOT_PRESENT_OFFSET, 13813 },
+  { 0xfe32, G_UNICODE_NOT_PRESENT_OFFSET, 13817 },
+  { 0xfe33, G_UNICODE_NOT_PRESENT_OFFSET, 13821 },
+  { 0xfe34, G_UNICODE_NOT_PRESENT_OFFSET, 13821 },
+  { 0xfe35, G_UNICODE_NOT_PRESENT_OFFSET, 4965 },
+  { 0xfe36, G_UNICODE_NOT_PRESENT_OFFSET, 4967 },
+  { 0xfe37, G_UNICODE_NOT_PRESENT_OFFSET, 13823 },
+  { 0xfe38, G_UNICODE_NOT_PRESENT_OFFSET, 13825 },
+  { 0xfe39, G_UNICODE_NOT_PRESENT_OFFSET, 13827 },
+  { 0xfe3a, G_UNICODE_NOT_PRESENT_OFFSET, 13831 },
+  { 0xfe3b, G_UNICODE_NOT_PRESENT_OFFSET, 13835 },
+  { 0xfe3c, G_UNICODE_NOT_PRESENT_OFFSET, 13839 },
+  { 0xfe3d, G_UNICODE_NOT_PRESENT_OFFSET, 13843 },
+  { 0xfe3e, G_UNICODE_NOT_PRESENT_OFFSET, 13847 },
+  { 0xfe3f, G_UNICODE_NOT_PRESENT_OFFSET, 5524 },
+  { 0xfe40, G_UNICODE_NOT_PRESENT_OFFSET, 5528 },
+  { 0xfe41, G_UNICODE_NOT_PRESENT_OFFSET, 13851 },
+  { 0xfe42, G_UNICODE_NOT_PRESENT_OFFSET, 13855 },
+  { 0xfe43, G_UNICODE_NOT_PRESENT_OFFSET, 13859 },
+  { 0xfe44, G_UNICODE_NOT_PRESENT_OFFSET, 13863 },
+  { 0xfe49, G_UNICODE_NOT_PRESENT_OFFSET, 4915 },
+  { 0xfe4a, G_UNICODE_NOT_PRESENT_OFFSET, 4915 },
+  { 0xfe4b, G_UNICODE_NOT_PRESENT_OFFSET, 4915 },
+  { 0xfe4c, G_UNICODE_NOT_PRESENT_OFFSET, 4915 },
+  { 0xfe4d, G_UNICODE_NOT_PRESENT_OFFSET, 13821 },
+  { 0xfe4e, G_UNICODE_NOT_PRESENT_OFFSET, 13821 },
+  { 0xfe4f, G_UNICODE_NOT_PRESENT_OFFSET, 13821 },
+  { 0xfe50, G_UNICODE_NOT_PRESENT_OFFSET, 13867 },
+  { 0xfe51, G_UNICODE_NOT_PRESENT_OFFSET, 13869 },
+  { 0xfe52, G_UNICODE_NOT_PRESENT_OFFSET, 4869 },
+  { 0xfe54, G_UNICODE_NOT_PRESENT_OFFSET, 1248 },
+  { 0xfe55, G_UNICODE_NOT_PRESENT_OFFSET, 13873 },
+  { 0xfe56, G_UNICODE_NOT_PRESENT_OFFSET, 13875 },
+  { 0xfe57, G_UNICODE_NOT_PRESENT_OFFSET, 13877 },
+  { 0xfe58, G_UNICODE_NOT_PRESENT_OFFSET, 13813 },
+  { 0xfe59, G_UNICODE_NOT_PRESENT_OFFSET, 4965 },
+  { 0xfe5a, G_UNICODE_NOT_PRESENT_OFFSET, 4967 },
+  { 0xfe5b, G_UNICODE_NOT_PRESENT_OFFSET, 13823 },
+  { 0xfe5c, G_UNICODE_NOT_PRESENT_OFFSET, 13825 },
+  { 0xfe5d, G_UNICODE_NOT_PRESENT_OFFSET, 13827 },
+  { 0xfe5e, G_UNICODE_NOT_PRESENT_OFFSET, 13831 },
+  { 0xfe5f, G_UNICODE_NOT_PRESENT_OFFSET, 13879 },
+  { 0xfe60, G_UNICODE_NOT_PRESENT_OFFSET, 13881 },
+  { 0xfe61, G_UNICODE_NOT_PRESENT_OFFSET, 13883 },
+  { 0xfe62, G_UNICODE_NOT_PRESENT_OFFSET, 4957 },
+  { 0xfe63, G_UNICODE_NOT_PRESENT_OFFSET, 13885 },
+  { 0xfe64, G_UNICODE_NOT_PRESENT_OFFSET, 13887 },
+  { 0xfe65, G_UNICODE_NOT_PRESENT_OFFSET, 13889 },
+  { 0xfe66, G_UNICODE_NOT_PRESENT_OFFSET, 4963 },
+  { 0xfe68, G_UNICODE_NOT_PRESENT_OFFSET, 13891 },
+  { 0xfe69, G_UNICODE_NOT_PRESENT_OFFSET, 13893 },
+  { 0xfe6a, G_UNICODE_NOT_PRESENT_OFFSET, 13895 },
+  { 0xfe6b, G_UNICODE_NOT_PRESENT_OFFSET, 13897 },
+  { 0xfe70, G_UNICODE_NOT_PRESENT_OFFSET, 13899 },
+  { 0xfe71, G_UNICODE_NOT_PRESENT_OFFSET, 13903 },
+  { 0xfe72, G_UNICODE_NOT_PRESENT_OFFSET, 13908 },
+  { 0xfe74, G_UNICODE_NOT_PRESENT_OFFSET, 13912 },
+  { 0xfe76, G_UNICODE_NOT_PRESENT_OFFSET, 13916 },
+  { 0xfe77, G_UNICODE_NOT_PRESENT_OFFSET, 13920 },
+  { 0xfe78, G_UNICODE_NOT_PRESENT_OFFSET, 13925 },
+  { 0xfe79, G_UNICODE_NOT_PRESENT_OFFSET, 13929 },
+  { 0xfe7a, G_UNICODE_NOT_PRESENT_OFFSET, 13934 },
+  { 0xfe7b, G_UNICODE_NOT_PRESENT_OFFSET, 13938 },
+  { 0xfe7c, G_UNICODE_NOT_PRESENT_OFFSET, 13943 },
+  { 0xfe7d, G_UNICODE_NOT_PRESENT_OFFSET, 13947 },
+  { 0xfe7e, G_UNICODE_NOT_PRESENT_OFFSET, 13952 },
+  { 0xfe7f, G_UNICODE_NOT_PRESENT_OFFSET, 13956 },
+  { 0xfe80, G_UNICODE_NOT_PRESENT_OFFSET, 13961 },
+  { 0xfe81, G_UNICODE_NOT_PRESENT_OFFSET, 1673 },
+  { 0xfe82, G_UNICODE_NOT_PRESENT_OFFSET, 1673 },
+  { 0xfe83, G_UNICODE_NOT_PRESENT_OFFSET, 1678 },
+  { 0xfe84, G_UNICODE_NOT_PRESENT_OFFSET, 1678 },
+  { 0xfe85, G_UNICODE_NOT_PRESENT_OFFSET, 1683 },
+  { 0xfe86, G_UNICODE_NOT_PRESENT_OFFSET, 1683 },
+  { 0xfe87, G_UNICODE_NOT_PRESENT_OFFSET, 1688 },
+  { 0xfe88, G_UNICODE_NOT_PRESENT_OFFSET, 1688 },
+  { 0xfe89, G_UNICODE_NOT_PRESENT_OFFSET, 1693 },
+  { 0xfe8a, G_UNICODE_NOT_PRESENT_OFFSET, 1693 },
+  { 0xfe8b, G_UNICODE_NOT_PRESENT_OFFSET, 1693 },
+  { 0xfe8c, G_UNICODE_NOT_PRESENT_OFFSET, 1693 },
+  { 0xfe8d, G_UNICODE_NOT_PRESENT_OFFSET, 13964 },
+  { 0xfe8e, G_UNICODE_NOT_PRESENT_OFFSET, 13964 },
+  { 0xfe8f, G_UNICODE_NOT_PRESENT_OFFSET, 13967 },
+  { 0xfe90, G_UNICODE_NOT_PRESENT_OFFSET, 13967 },
+  { 0xfe91, G_UNICODE_NOT_PRESENT_OFFSET, 13967 },
+  { 0xfe92, G_UNICODE_NOT_PRESENT_OFFSET, 13967 },
+  { 0xfe93, G_UNICODE_NOT_PRESENT_OFFSET, 13970 },
+  { 0xfe94, G_UNICODE_NOT_PRESENT_OFFSET, 13970 },
+  { 0xfe95, G_UNICODE_NOT_PRESENT_OFFSET, 13973 },
+  { 0xfe96, G_UNICODE_NOT_PRESENT_OFFSET, 13973 },
+  { 0xfe97, G_UNICODE_NOT_PRESENT_OFFSET, 13973 },
+  { 0xfe98, G_UNICODE_NOT_PRESENT_OFFSET, 13973 },
+  { 0xfe99, G_UNICODE_NOT_PRESENT_OFFSET, 13976 },
+  { 0xfe9a, G_UNICODE_NOT_PRESENT_OFFSET, 13976 },
+  { 0xfe9b, G_UNICODE_NOT_PRESENT_OFFSET, 13976 },
+  { 0xfe9c, G_UNICODE_NOT_PRESENT_OFFSET, 13976 },
+  { 0xfe9d, G_UNICODE_NOT_PRESENT_OFFSET, 13979 },
+  { 0xfe9e, G_UNICODE_NOT_PRESENT_OFFSET, 13979 },
+  { 0xfe9f, G_UNICODE_NOT_PRESENT_OFFSET, 13979 },
+  { 0xfea0, G_UNICODE_NOT_PRESENT_OFFSET, 13979 },
+  { 0xfea1, G_UNICODE_NOT_PRESENT_OFFSET, 13982 },
+  { 0xfea2, G_UNICODE_NOT_PRESENT_OFFSET, 13982 },
+  { 0xfea3, G_UNICODE_NOT_PRESENT_OFFSET, 13982 },
+  { 0xfea4, G_UNICODE_NOT_PRESENT_OFFSET, 13982 },
+  { 0xfea5, G_UNICODE_NOT_PRESENT_OFFSET, 13985 },
+  { 0xfea6, G_UNICODE_NOT_PRESENT_OFFSET, 13985 },
+  { 0xfea7, G_UNICODE_NOT_PRESENT_OFFSET, 13985 },
+  { 0xfea8, G_UNICODE_NOT_PRESENT_OFFSET, 13985 },
+  { 0xfea9, G_UNICODE_NOT_PRESENT_OFFSET, 13988 },
+  { 0xfeaa, G_UNICODE_NOT_PRESENT_OFFSET, 13988 },
+  { 0xfeab, G_UNICODE_NOT_PRESENT_OFFSET, 13991 },
+  { 0xfeac, G_UNICODE_NOT_PRESENT_OFFSET, 13991 },
+  { 0xfead, G_UNICODE_NOT_PRESENT_OFFSET, 13994 },
+  { 0xfeae, G_UNICODE_NOT_PRESENT_OFFSET, 13994 },
+  { 0xfeaf, G_UNICODE_NOT_PRESENT_OFFSET, 13997 },
+  { 0xfeb0, G_UNICODE_NOT_PRESENT_OFFSET, 13997 },
+  { 0xfeb1, G_UNICODE_NOT_PRESENT_OFFSET, 14000 },
+  { 0xfeb2, G_UNICODE_NOT_PRESENT_OFFSET, 14000 },
+  { 0xfeb3, G_UNICODE_NOT_PRESENT_OFFSET, 14000 },
+  { 0xfeb4, G_UNICODE_NOT_PRESENT_OFFSET, 14000 },
+  { 0xfeb5, G_UNICODE_NOT_PRESENT_OFFSET, 14003 },
+  { 0xfeb6, G_UNICODE_NOT_PRESENT_OFFSET, 14003 },
+  { 0xfeb7, G_UNICODE_NOT_PRESENT_OFFSET, 14003 },
+  { 0xfeb8, G_UNICODE_NOT_PRESENT_OFFSET, 14003 },
+  { 0xfeb9, G_UNICODE_NOT_PRESENT_OFFSET, 14006 },
+  { 0xfeba, G_UNICODE_NOT_PRESENT_OFFSET, 14006 },
+  { 0xfebb, G_UNICODE_NOT_PRESENT_OFFSET, 14006 },
+  { 0xfebc, G_UNICODE_NOT_PRESENT_OFFSET, 14006 },
+  { 0xfebd, G_UNICODE_NOT_PRESENT_OFFSET, 14009 },
+  { 0xfebe, G_UNICODE_NOT_PRESENT_OFFSET, 14009 },
+  { 0xfebf, G_UNICODE_NOT_PRESENT_OFFSET, 14009 },
+  { 0xfec0, G_UNICODE_NOT_PRESENT_OFFSET, 14009 },
+  { 0xfec1, G_UNICODE_NOT_PRESENT_OFFSET, 14012 },
+  { 0xfec2, G_UNICODE_NOT_PRESENT_OFFSET, 14012 },
+  { 0xfec3, G_UNICODE_NOT_PRESENT_OFFSET, 14012 },
+  { 0xfec4, G_UNICODE_NOT_PRESENT_OFFSET, 14012 },
+  { 0xfec5, G_UNICODE_NOT_PRESENT_OFFSET, 14015 },
+  { 0xfec6, G_UNICODE_NOT_PRESENT_OFFSET, 14015 },
+  { 0xfec7, G_UNICODE_NOT_PRESENT_OFFSET, 14015 },
+  { 0xfec8, G_UNICODE_NOT_PRESENT_OFFSET, 14015 },
+  { 0xfec9, G_UNICODE_NOT_PRESENT_OFFSET, 14018 },
+  { 0xfeca, G_UNICODE_NOT_PRESENT_OFFSET, 14018 },
+  { 0xfecb, G_UNICODE_NOT_PRESENT_OFFSET, 14018 },
+  { 0xfecc, G_UNICODE_NOT_PRESENT_OFFSET, 14018 },
+  { 0xfecd, G_UNICODE_NOT_PRESENT_OFFSET, 14021 },
+  { 0xfece, G_UNICODE_NOT_PRESENT_OFFSET, 14021 },
+  { 0xfecf, G_UNICODE_NOT_PRESENT_OFFSET, 14021 },
+  { 0xfed0, G_UNICODE_NOT_PRESENT_OFFSET, 14021 },
+  { 0xfed1, G_UNICODE_NOT_PRESENT_OFFSET, 14024 },
+  { 0xfed2, G_UNICODE_NOT_PRESENT_OFFSET, 14024 },
+  { 0xfed3, G_UNICODE_NOT_PRESENT_OFFSET, 14024 },
+  { 0xfed4, G_UNICODE_NOT_PRESENT_OFFSET, 14024 },
+  { 0xfed5, G_UNICODE_NOT_PRESENT_OFFSET, 14027 },
+  { 0xfed6, G_UNICODE_NOT_PRESENT_OFFSET, 14027 },
+  { 0xfed7, G_UNICODE_NOT_PRESENT_OFFSET, 14027 },
+  { 0xfed8, G_UNICODE_NOT_PRESENT_OFFSET, 14027 },
+  { 0xfed9, G_UNICODE_NOT_PRESENT_OFFSET, 14030 },
+  { 0xfeda, G_UNICODE_NOT_PRESENT_OFFSET, 14030 },
+  { 0xfedb, G_UNICODE_NOT_PRESENT_OFFSET, 14030 },
+  { 0xfedc, G_UNICODE_NOT_PRESENT_OFFSET, 14030 },
+  { 0xfedd, G_UNICODE_NOT_PRESENT_OFFSET, 14033 },
+  { 0xfede, G_UNICODE_NOT_PRESENT_OFFSET, 14033 },
+  { 0xfedf, G_UNICODE_NOT_PRESENT_OFFSET, 14033 },
+  { 0xfee0, G_UNICODE_NOT_PRESENT_OFFSET, 14033 },
+  { 0xfee1, G_UNICODE_NOT_PRESENT_OFFSET, 14036 },
+  { 0xfee2, G_UNICODE_NOT_PRESENT_OFFSET, 14036 },
+  { 0xfee3, G_UNICODE_NOT_PRESENT_OFFSET, 14036 },
+  { 0xfee4, G_UNICODE_NOT_PRESENT_OFFSET, 14036 },
+  { 0xfee5, G_UNICODE_NOT_PRESENT_OFFSET, 14039 },
+  { 0xfee6, G_UNICODE_NOT_PRESENT_OFFSET, 14039 },
+  { 0xfee7, G_UNICODE_NOT_PRESENT_OFFSET, 14039 },
+  { 0xfee8, G_UNICODE_NOT_PRESENT_OFFSET, 14039 },
+  { 0xfee9, G_UNICODE_NOT_PRESENT_OFFSET, 14042 },
+  { 0xfeea, G_UNICODE_NOT_PRESENT_OFFSET, 14042 },
+  { 0xfeeb, G_UNICODE_NOT_PRESENT_OFFSET, 14042 },
+  { 0xfeec, G_UNICODE_NOT_PRESENT_OFFSET, 14042 },
+  { 0xfeed, G_UNICODE_NOT_PRESENT_OFFSET, 14045 },
+  { 0xfeee, G_UNICODE_NOT_PRESENT_OFFSET, 14045 },
+  { 0xfeef, G_UNICODE_NOT_PRESENT_OFFSET, 12110 },
+  { 0xfef0, G_UNICODE_NOT_PRESENT_OFFSET, 12110 },
+  { 0xfef1, G_UNICODE_NOT_PRESENT_OFFSET, 14048 },
+  { 0xfef2, G_UNICODE_NOT_PRESENT_OFFSET, 14048 },
+  { 0xfef3, G_UNICODE_NOT_PRESENT_OFFSET, 14048 },
+  { 0xfef4, G_UNICODE_NOT_PRESENT_OFFSET, 14048 },
+  { 0xfef5, G_UNICODE_NOT_PRESENT_OFFSET, 14051 },
+  { 0xfef6, G_UNICODE_NOT_PRESENT_OFFSET, 14051 },
+  { 0xfef7, G_UNICODE_NOT_PRESENT_OFFSET, 14058 },
+  { 0xfef8, G_UNICODE_NOT_PRESENT_OFFSET, 14058 },
+  { 0xfef9, G_UNICODE_NOT_PRESENT_OFFSET, 14065 },
+  { 0xfefa, G_UNICODE_NOT_PRESENT_OFFSET, 14065 },
+  { 0xfefb, G_UNICODE_NOT_PRESENT_OFFSET, 14072 },
+  { 0xfefc, G_UNICODE_NOT_PRESENT_OFFSET, 14072 },
+  { 0xff01, G_UNICODE_NOT_PRESENT_OFFSET, 13877 },
+  { 0xff02, G_UNICODE_NOT_PRESENT_OFFSET, 14077 },
+  { 0xff03, G_UNICODE_NOT_PRESENT_OFFSET, 13879 },
+  { 0xff04, G_UNICODE_NOT_PRESENT_OFFSET, 13893 },
+  { 0xff05, G_UNICODE_NOT_PRESENT_OFFSET, 13895 },
+  { 0xff06, G_UNICODE_NOT_PRESENT_OFFSET, 13881 },
+  { 0xff07, G_UNICODE_NOT_PRESENT_OFFSET, 14079 },
+  { 0xff08, G_UNICODE_NOT_PRESENT_OFFSET, 4965 },
+  { 0xff09, G_UNICODE_NOT_PRESENT_OFFSET, 4967 },
+  { 0xff0a, G_UNICODE_NOT_PRESENT_OFFSET, 13883 },
+  { 0xff0b, G_UNICODE_NOT_PRESENT_OFFSET, 4957 },
+  { 0xff0c, G_UNICODE_NOT_PRESENT_OFFSET, 13867 },
+  { 0xff0d, G_UNICODE_NOT_PRESENT_OFFSET, 13885 },
+  { 0xff0e, G_UNICODE_NOT_PRESENT_OFFSET, 4869 },
+  { 0xff0f, G_UNICODE_NOT_PRESENT_OFFSET, 14081 },
+  { 0xff10, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0xff11, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0xff12, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0xff13, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0xff14, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0xff15, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0xff16, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0xff17, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0xff18, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0xff19, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0xff1a, G_UNICODE_NOT_PRESENT_OFFSET, 13873 },
+  { 0xff1b, G_UNICODE_NOT_PRESENT_OFFSET, 1248 },
+  { 0xff1c, G_UNICODE_NOT_PRESENT_OFFSET, 13887 },
+  { 0xff1d, G_UNICODE_NOT_PRESENT_OFFSET, 4963 },
+  { 0xff1e, G_UNICODE_NOT_PRESENT_OFFSET, 13889 },
+  { 0xff1f, G_UNICODE_NOT_PRESENT_OFFSET, 13875 },
+  { 0xff20, G_UNICODE_NOT_PRESENT_OFFSET, 13897 },
+  { 0xff21, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0xff22, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0xff23, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0xff24, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0xff25, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0xff26, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0xff27, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0xff28, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0xff29, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0xff2a, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0xff2b, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0xff2c, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0xff2d, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0xff2e, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0xff2f, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0xff30, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0xff31, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0xff32, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0xff33, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0xff34, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0xff35, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0xff36, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0xff37, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0xff38, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0xff39, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0xff3a, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0xff3b, G_UNICODE_NOT_PRESENT_OFFSET, 14083 },
+  { 0xff3c, G_UNICODE_NOT_PRESENT_OFFSET, 13891 },
+  { 0xff3d, G_UNICODE_NOT_PRESENT_OFFSET, 14085 },
+  { 0xff3e, G_UNICODE_NOT_PRESENT_OFFSET, 14087 },
+  { 0xff3f, G_UNICODE_NOT_PRESENT_OFFSET, 13821 },
+  { 0xff40, G_UNICODE_NOT_PRESENT_OFFSET, 4798 },
+  { 0xff41, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0xff42, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0xff43, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0xff44, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0xff45, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0xff46, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0xff47, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0xff48, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0xff49, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0xff4a, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0xff4b, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0xff4c, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0xff4d, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0xff4e, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0xff4f, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0xff50, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0xff51, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0xff52, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0xff53, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0xff54, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0xff55, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0xff56, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0xff57, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0xff58, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0xff59, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0xff5a, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0xff5b, G_UNICODE_NOT_PRESENT_OFFSET, 13823 },
+  { 0xff5c, G_UNICODE_NOT_PRESENT_OFFSET, 14089 },
+  { 0xff5d, G_UNICODE_NOT_PRESENT_OFFSET, 13825 },
+  { 0xff5e, G_UNICODE_NOT_PRESENT_OFFSET, 14091 },
+  { 0xff5f, G_UNICODE_NOT_PRESENT_OFFSET, 14093 },
+  { 0xff60, G_UNICODE_NOT_PRESENT_OFFSET, 14097 },
+  { 0xff61, G_UNICODE_NOT_PRESENT_OFFSET, 14101 },
+  { 0xff62, G_UNICODE_NOT_PRESENT_OFFSET, 13851 },
+  { 0xff63, G_UNICODE_NOT_PRESENT_OFFSET, 13855 },
+  { 0xff64, G_UNICODE_NOT_PRESENT_OFFSET, 13869 },
+  { 0xff65, G_UNICODE_NOT_PRESENT_OFFSET, 14105 },
+  { 0xff66, G_UNICODE_NOT_PRESENT_OFFSET, 8615 },
+  { 0xff67, G_UNICODE_NOT_PRESENT_OFFSET, 14109 },
+  { 0xff68, G_UNICODE_NOT_PRESENT_OFFSET, 14113 },
+  { 0xff69, G_UNICODE_NOT_PRESENT_OFFSET, 14117 },
+  { 0xff6a, G_UNICODE_NOT_PRESENT_OFFSET, 14121 },
+  { 0xff6b, G_UNICODE_NOT_PRESENT_OFFSET, 14125 },
+  { 0xff6c, G_UNICODE_NOT_PRESENT_OFFSET, 14129 },
+  { 0xff6d, G_UNICODE_NOT_PRESENT_OFFSET, 14133 },
+  { 0xff6e, G_UNICODE_NOT_PRESENT_OFFSET, 14137 },
+  { 0xff6f, G_UNICODE_NOT_PRESENT_OFFSET, 14141 },
+  { 0xff70, G_UNICODE_NOT_PRESENT_OFFSET, 14145 },
+  { 0xff71, G_UNICODE_NOT_PRESENT_OFFSET, 8431 },
+  { 0xff72, G_UNICODE_NOT_PRESENT_OFFSET, 8435 },
+  { 0xff73, G_UNICODE_NOT_PRESENT_OFFSET, 8439 },
+  { 0xff74, G_UNICODE_NOT_PRESENT_OFFSET, 8443 },
+  { 0xff75, G_UNICODE_NOT_PRESENT_OFFSET, 8447 },
+  { 0xff76, G_UNICODE_NOT_PRESENT_OFFSET, 8451 },
+  { 0xff77, G_UNICODE_NOT_PRESENT_OFFSET, 8455 },
+  { 0xff78, G_UNICODE_NOT_PRESENT_OFFSET, 8459 },
+  { 0xff79, G_UNICODE_NOT_PRESENT_OFFSET, 8463 },
+  { 0xff7a, G_UNICODE_NOT_PRESENT_OFFSET, 8467 },
+  { 0xff7b, G_UNICODE_NOT_PRESENT_OFFSET, 8471 },
+  { 0xff7c, G_UNICODE_NOT_PRESENT_OFFSET, 8475 },
+  { 0xff7d, G_UNICODE_NOT_PRESENT_OFFSET, 8479 },
+  { 0xff7e, G_UNICODE_NOT_PRESENT_OFFSET, 8483 },
+  { 0xff7f, G_UNICODE_NOT_PRESENT_OFFSET, 8487 },
+  { 0xff80, G_UNICODE_NOT_PRESENT_OFFSET, 8491 },
+  { 0xff81, G_UNICODE_NOT_PRESENT_OFFSET, 8495 },
+  { 0xff82, G_UNICODE_NOT_PRESENT_OFFSET, 8499 },
+  { 0xff83, G_UNICODE_NOT_PRESENT_OFFSET, 8503 },
+  { 0xff84, G_UNICODE_NOT_PRESENT_OFFSET, 8507 },
+  { 0xff85, G_UNICODE_NOT_PRESENT_OFFSET, 8511 },
+  { 0xff86, G_UNICODE_NOT_PRESENT_OFFSET, 8515 },
+  { 0xff87, G_UNICODE_NOT_PRESENT_OFFSET, 8519 },
+  { 0xff88, G_UNICODE_NOT_PRESENT_OFFSET, 8523 },
+  { 0xff89, G_UNICODE_NOT_PRESENT_OFFSET, 8527 },
+  { 0xff8a, G_UNICODE_NOT_PRESENT_OFFSET, 8531 },
+  { 0xff8b, G_UNICODE_NOT_PRESENT_OFFSET, 8535 },
+  { 0xff8c, G_UNICODE_NOT_PRESENT_OFFSET, 8539 },
+  { 0xff8d, G_UNICODE_NOT_PRESENT_OFFSET, 8543 },
+  { 0xff8e, G_UNICODE_NOT_PRESENT_OFFSET, 8547 },
+  { 0xff8f, G_UNICODE_NOT_PRESENT_OFFSET, 8551 },
+  { 0xff90, G_UNICODE_NOT_PRESENT_OFFSET, 8555 },
+  { 0xff91, G_UNICODE_NOT_PRESENT_OFFSET, 8559 },
+  { 0xff92, G_UNICODE_NOT_PRESENT_OFFSET, 8563 },
+  { 0xff93, G_UNICODE_NOT_PRESENT_OFFSET, 8567 },
+  { 0xff94, G_UNICODE_NOT_PRESENT_OFFSET, 8571 },
+  { 0xff95, G_UNICODE_NOT_PRESENT_OFFSET, 8575 },
+  { 0xff96, G_UNICODE_NOT_PRESENT_OFFSET, 8579 },
+  { 0xff97, G_UNICODE_NOT_PRESENT_OFFSET, 8583 },
+  { 0xff98, G_UNICODE_NOT_PRESENT_OFFSET, 8587 },
+  { 0xff99, G_UNICODE_NOT_PRESENT_OFFSET, 8591 },
+  { 0xff9a, G_UNICODE_NOT_PRESENT_OFFSET, 8595 },
+  { 0xff9b, G_UNICODE_NOT_PRESENT_OFFSET, 8599 },
+  { 0xff9c, G_UNICODE_NOT_PRESENT_OFFSET, 8603 },
+  { 0xff9d, G_UNICODE_NOT_PRESENT_OFFSET, 14149 },
+  { 0xff9e, G_UNICODE_NOT_PRESENT_OFFSET, 14153 },
+  { 0xff9f, G_UNICODE_NOT_PRESENT_OFFSET, 14157 },
+  { 0xffa0, G_UNICODE_NOT_PRESENT_OFFSET, 7405 },
+  { 0xffa1, G_UNICODE_NOT_PRESENT_OFFSET, 7201 },
+  { 0xffa2, G_UNICODE_NOT_PRESENT_OFFSET, 7205 },
+  { 0xffa3, G_UNICODE_NOT_PRESENT_OFFSET, 7209 },
+  { 0xffa4, G_UNICODE_NOT_PRESENT_OFFSET, 7213 },
+  { 0xffa5, G_UNICODE_NOT_PRESENT_OFFSET, 7217 },
+  { 0xffa6, G_UNICODE_NOT_PRESENT_OFFSET, 7221 },
+  { 0xffa7, G_UNICODE_NOT_PRESENT_OFFSET, 7225 },
+  { 0xffa8, G_UNICODE_NOT_PRESENT_OFFSET, 7229 },
+  { 0xffa9, G_UNICODE_NOT_PRESENT_OFFSET, 7233 },
+  { 0xffaa, G_UNICODE_NOT_PRESENT_OFFSET, 7237 },
+  { 0xffab, G_UNICODE_NOT_PRESENT_OFFSET, 7241 },
+  { 0xffac, G_UNICODE_NOT_PRESENT_OFFSET, 7245 },
+  { 0xffad, G_UNICODE_NOT_PRESENT_OFFSET, 7249 },
+  { 0xffae, G_UNICODE_NOT_PRESENT_OFFSET, 7253 },
+  { 0xffaf, G_UNICODE_NOT_PRESENT_OFFSET, 7257 },
+  { 0xffb0, G_UNICODE_NOT_PRESENT_OFFSET, 7261 },
+  { 0xffb1, G_UNICODE_NOT_PRESENT_OFFSET, 7265 },
+  { 0xffb2, G_UNICODE_NOT_PRESENT_OFFSET, 7269 },
+  { 0xffb3, G_UNICODE_NOT_PRESENT_OFFSET, 7273 },
+  { 0xffb4, G_UNICODE_NOT_PRESENT_OFFSET, 7277 },
+  { 0xffb5, G_UNICODE_NOT_PRESENT_OFFSET, 7281 },
+  { 0xffb6, G_UNICODE_NOT_PRESENT_OFFSET, 7285 },
+  { 0xffb7, G_UNICODE_NOT_PRESENT_OFFSET, 7289 },
+  { 0xffb8, G_UNICODE_NOT_PRESENT_OFFSET, 7293 },
+  { 0xffb9, G_UNICODE_NOT_PRESENT_OFFSET, 7297 },
+  { 0xffba, G_UNICODE_NOT_PRESENT_OFFSET, 7301 },
+  { 0xffbb, G_UNICODE_NOT_PRESENT_OFFSET, 7305 },
+  { 0xffbc, G_UNICODE_NOT_PRESENT_OFFSET, 7309 },
+  { 0xffbd, G_UNICODE_NOT_PRESENT_OFFSET, 7313 },
+  { 0xffbe, G_UNICODE_NOT_PRESENT_OFFSET, 7317 },
+  { 0xffc2, G_UNICODE_NOT_PRESENT_OFFSET, 7321 },
+  { 0xffc3, G_UNICODE_NOT_PRESENT_OFFSET, 7325 },
+  { 0xffc4, G_UNICODE_NOT_PRESENT_OFFSET, 7329 },
+  { 0xffc5, G_UNICODE_NOT_PRESENT_OFFSET, 7333 },
+  { 0xffc6, G_UNICODE_NOT_PRESENT_OFFSET, 7337 },
+  { 0xffc7, G_UNICODE_NOT_PRESENT_OFFSET, 7341 },
+  { 0xffca, G_UNICODE_NOT_PRESENT_OFFSET, 7345 },
+  { 0xffcb, G_UNICODE_NOT_PRESENT_OFFSET, 7349 },
+  { 0xffcc, G_UNICODE_NOT_PRESENT_OFFSET, 7353 },
+  { 0xffcd, G_UNICODE_NOT_PRESENT_OFFSET, 7357 },
+  { 0xffce, G_UNICODE_NOT_PRESENT_OFFSET, 7361 },
+  { 0xffcf, G_UNICODE_NOT_PRESENT_OFFSET, 7365 },
+  { 0xffd2, G_UNICODE_NOT_PRESENT_OFFSET, 7369 },
+  { 0xffd3, G_UNICODE_NOT_PRESENT_OFFSET, 7373 },
+  { 0xffd4, G_UNICODE_NOT_PRESENT_OFFSET, 7377 },
+  { 0xffd5, G_UNICODE_NOT_PRESENT_OFFSET, 7381 },
+  { 0xffd6, G_UNICODE_NOT_PRESENT_OFFSET, 7385 },
+  { 0xffd7, G_UNICODE_NOT_PRESENT_OFFSET, 7389 },
+  { 0xffda, G_UNICODE_NOT_PRESENT_OFFSET, 7393 },
+  { 0xffdb, G_UNICODE_NOT_PRESENT_OFFSET, 7397 },
+  { 0xffdc, G_UNICODE_NOT_PRESENT_OFFSET, 7401 },
+  { 0xffe0, G_UNICODE_NOT_PRESENT_OFFSET, 14161 },
+  { 0xffe1, G_UNICODE_NOT_PRESENT_OFFSET, 14164 },
+  { 0xffe2, G_UNICODE_NOT_PRESENT_OFFSET, 14167 },
+  { 0xffe3, G_UNICODE_NOT_PRESENT_OFFSET, 8 },
+  { 0xffe4, G_UNICODE_NOT_PRESENT_OFFSET, 14170 },
+  { 0xffe5, G_UNICODE_NOT_PRESENT_OFFSET, 14173 },
+  { 0xffe6, G_UNICODE_NOT_PRESENT_OFFSET, 14176 },
+  { 0xffe8, G_UNICODE_NOT_PRESENT_OFFSET, 14180 },
+  { 0xffe9, G_UNICODE_NOT_PRESENT_OFFSET, 14184 },
+  { 0xffea, G_UNICODE_NOT_PRESENT_OFFSET, 14188 },
+  { 0xffeb, G_UNICODE_NOT_PRESENT_OFFSET, 14192 },
+  { 0xffec, G_UNICODE_NOT_PRESENT_OFFSET, 14196 },
+  { 0xffed, G_UNICODE_NOT_PRESENT_OFFSET, 14200 },
+  { 0xffee, G_UNICODE_NOT_PRESENT_OFFSET, 14204 },
+  { 0x1d15e, 14208, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d15f, 14217, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d160, 14226, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d161, 14239, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d162, 14252, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d163, 14265, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d164, 14278, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d1bb, 14291, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d1bc, 14300, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d1bd, 14309, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d1be, 14322, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d1bf, 14335, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d1c0, 14348, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x1d400, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d401, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d402, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d403, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d404, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d405, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d406, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d407, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d408, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d409, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d40a, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d40b, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d40c, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d40d, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d40e, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d40f, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d410, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d411, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d412, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d413, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d414, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d415, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d416, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d417, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d418, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d419, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d41a, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d41b, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d41c, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d41d, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d41e, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d41f, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d420, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d421, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d422, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d423, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d424, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d425, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d426, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d427, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d428, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d429, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d42a, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d42b, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d42c, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d42d, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d42e, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d42f, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d430, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d431, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d432, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d433, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d434, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d435, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d436, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d437, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d438, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d439, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d43a, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d43b, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d43c, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d43d, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d43e, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d43f, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d440, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d441, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d442, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d443, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d444, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d445, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d446, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d447, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d448, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d449, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d44a, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d44b, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d44c, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d44d, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d44e, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d44f, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d450, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d451, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d452, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d453, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d454, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d456, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d457, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d458, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d459, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d45a, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d45b, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d45c, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d45d, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d45e, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d45f, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d460, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d461, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d462, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d463, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d464, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d465, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d466, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d467, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d468, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d469, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d46a, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d46b, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d46c, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d46d, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d46e, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d46f, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d470, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d471, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d472, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d473, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d474, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d475, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d476, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d477, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d478, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d479, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d47a, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d47b, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d47c, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d47d, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d47e, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d47f, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d480, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d481, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d482, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d483, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d484, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d485, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d486, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d487, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d488, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d489, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d48a, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d48b, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d48c, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d48d, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d48e, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d48f, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d490, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d491, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d492, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d493, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d494, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d495, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d496, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d497, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d498, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d499, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d49a, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d49b, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d49c, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d49e, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d49f, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d4a2, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d4a5, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d4a6, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d4a9, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d4aa, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d4ab, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d4ac, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d4ae, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d4af, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d4b0, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d4b1, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d4b2, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d4b3, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d4b4, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d4b5, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d4b6, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d4b7, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d4b8, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d4b9, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d4bb, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d4bd, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d4be, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d4bf, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d4c0, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d4c2, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d4c3, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d4c5, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d4c6, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d4c7, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d4c8, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d4c9, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d4ca, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d4cb, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d4cc, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d4cd, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d4ce, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d4cf, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d4d0, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d4d1, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d4d2, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d4d3, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d4d4, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d4d5, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d4d6, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d4d7, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d4d8, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d4d9, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d4da, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d4db, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d4dc, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d4dd, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d4de, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d4df, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d4e0, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d4e1, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d4e2, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d4e3, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d4e4, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d4e5, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d4e6, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d4e7, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d4e8, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d4e9, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d4ea, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d4eb, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d4ec, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d4ed, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d4ee, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d4ef, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d4f0, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d4f1, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d4f2, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d4f3, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d4f4, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d4f5, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d4f6, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d4f7, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d4f8, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d4f9, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d4fa, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d4fb, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d4fc, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d4fd, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d4fe, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d4ff, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d500, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d501, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d502, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d503, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d504, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d505, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d507, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d508, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d509, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d50a, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d50d, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d50e, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d50f, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d510, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d511, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d512, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d513, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d514, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d516, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d517, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d518, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d519, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d51a, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d51b, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d51c, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d51e, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d51f, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d520, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d521, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d522, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d523, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d524, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d525, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d526, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d527, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d528, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d529, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d52a, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d52b, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d52c, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d52d, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d52e, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d52f, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d530, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d531, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d532, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d533, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d534, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d535, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d536, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d537, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d538, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d539, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d53b, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d53c, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d53d, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d53e, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d540, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d541, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d542, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d543, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d544, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d546, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d54a, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d54b, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d54c, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d54d, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d54e, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d54f, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d550, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d552, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d553, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d554, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d555, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d556, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d557, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d558, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d559, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d55a, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d55b, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d55c, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d55d, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d55e, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d55f, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d560, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d561, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d562, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d563, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d564, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d565, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d566, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d567, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d568, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d569, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d56a, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d56b, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d56c, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d56d, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d56e, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d56f, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d570, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d571, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d572, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d573, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d574, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d575, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d576, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d577, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d578, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d579, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d57a, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d57b, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d57c, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d57d, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d57e, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d57f, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d580, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d581, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d582, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d583, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d584, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d585, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d586, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d587, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d588, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d589, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d58a, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d58b, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d58c, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d58d, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d58e, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d58f, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d590, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d591, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d592, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d593, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d594, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d595, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d596, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d597, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d598, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d599, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d59a, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d59b, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d59c, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d59d, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d59e, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d59f, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d5a0, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d5a1, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d5a2, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d5a3, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d5a4, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d5a5, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d5a6, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d5a7, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d5a8, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d5a9, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d5aa, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d5ab, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d5ac, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d5ad, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d5ae, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d5af, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d5b0, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d5b1, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d5b2, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d5b3, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d5b4, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d5b5, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d5b6, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d5b7, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d5b8, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d5b9, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d5ba, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d5bb, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d5bc, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d5bd, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d5be, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d5bf, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d5c0, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d5c1, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d5c2, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d5c3, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d5c4, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d5c5, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d5c6, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d5c7, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d5c8, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d5c9, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d5ca, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d5cb, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d5cc, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d5cd, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d5ce, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d5cf, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d5d0, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d5d1, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d5d2, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d5d3, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d5d4, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d5d5, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d5d6, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d5d7, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d5d8, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d5d9, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d5da, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d5db, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d5dc, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d5dd, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d5de, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d5df, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d5e0, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d5e1, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d5e2, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d5e3, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d5e4, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d5e5, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d5e6, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d5e7, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d5e8, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d5e9, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d5ea, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d5eb, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d5ec, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d5ed, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d5ee, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d5ef, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d5f0, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d5f1, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d5f2, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d5f3, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d5f4, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d5f5, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d5f6, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d5f7, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d5f8, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d5f9, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d5fa, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d5fb, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d5fc, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d5fd, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d5fe, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d5ff, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d600, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d601, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d602, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d603, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d604, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d605, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d606, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d607, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d608, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d609, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d60a, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d60b, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d60c, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d60d, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d60e, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d60f, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d610, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d611, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d612, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d613, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d614, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d615, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d616, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d617, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d618, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d619, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d61a, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d61b, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d61c, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d61d, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d61e, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d61f, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d620, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d621, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d622, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d623, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d624, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d625, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d626, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d627, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d628, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d629, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d62a, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d62b, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d62c, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d62d, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d62e, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d62f, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d630, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d631, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d632, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d633, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d634, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d635, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d636, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d637, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d638, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d639, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d63a, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d63b, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d63c, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d63d, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d63e, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d63f, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d640, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d641, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d642, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d643, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d644, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d645, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d646, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d647, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d648, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d649, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d64a, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d64b, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d64c, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d64d, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d64e, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d64f, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d650, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d651, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d652, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d653, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d654, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d655, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d656, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d657, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d658, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d659, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d65a, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d65b, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d65c, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d65d, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d65e, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d65f, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d660, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d661, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d662, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d663, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d664, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d665, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d666, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d667, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d668, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d669, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d66a, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d66b, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d66c, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d66d, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d66e, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d66f, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d670, G_UNICODE_NOT_PRESENT_OFFSET, 5831 },
+  { 0x1d671, G_UNICODE_NOT_PRESENT_OFFSET, 5042 },
+  { 0x1d672, G_UNICODE_NOT_PRESENT_OFFSET, 4982 },
+  { 0x1d673, G_UNICODE_NOT_PRESENT_OFFSET, 5077 },
+  { 0x1d674, G_UNICODE_NOT_PRESENT_OFFSET, 5046 },
+  { 0x1d675, G_UNICODE_NOT_PRESENT_OFFSET, 5048 },
+  { 0x1d676, G_UNICODE_NOT_PRESENT_OFFSET, 5833 },
+  { 0x1d677, G_UNICODE_NOT_PRESENT_OFFSET, 5005 },
+  { 0x1d678, G_UNICODE_NOT_PRESENT_OFFSET, 5010 },
+  { 0x1d679, G_UNICODE_NOT_PRESENT_OFFSET, 5835 },
+  { 0x1d67a, G_UNICODE_NOT_PRESENT_OFFSET, 5040 },
+  { 0x1d67b, G_UNICODE_NOT_PRESENT_OFFSET, 5012 },
+  { 0x1d67c, G_UNICODE_NOT_PRESENT_OFFSET, 5050 },
+  { 0x1d67d, G_UNICODE_NOT_PRESENT_OFFSET, 5014 },
+  { 0x1d67e, G_UNICODE_NOT_PRESENT_OFFSET, 5837 },
+  { 0x1d67f, G_UNICODE_NOT_PRESENT_OFFSET, 5019 },
+  { 0x1d680, G_UNICODE_NOT_PRESENT_OFFSET, 5021 },
+  { 0x1d681, G_UNICODE_NOT_PRESENT_OFFSET, 5023 },
+  { 0x1d682, G_UNICODE_NOT_PRESENT_OFFSET, 5839 },
+  { 0x1d683, G_UNICODE_NOT_PRESENT_OFFSET, 5841 },
+  { 0x1d684, G_UNICODE_NOT_PRESENT_OFFSET, 5843 },
+  { 0x1d685, G_UNICODE_NOT_PRESENT_OFFSET, 5168 },
+  { 0x1d686, G_UNICODE_NOT_PRESENT_OFFSET, 5845 },
+  { 0x1d687, G_UNICODE_NOT_PRESENT_OFFSET, 5185 },
+  { 0x1d688, G_UNICODE_NOT_PRESENT_OFFSET, 5847 },
+  { 0x1d689, G_UNICODE_NOT_PRESENT_OFFSET, 5035 },
+  { 0x1d68a, G_UNICODE_NOT_PRESENT_OFFSET, 6 },
+  { 0x1d68b, G_UNICODE_NOT_PRESENT_OFFSET, 5849 },
+  { 0x1d68c, G_UNICODE_NOT_PRESENT_OFFSET, 5228 },
+  { 0x1d68d, G_UNICODE_NOT_PRESENT_OFFSET, 5079 },
+  { 0x1d68e, G_UNICODE_NOT_PRESENT_OFFSET, 5044 },
+  { 0x1d68f, G_UNICODE_NOT_PRESENT_OFFSET, 5851 },
+  { 0x1d690, G_UNICODE_NOT_PRESENT_OFFSET, 5003 },
+  { 0x1d691, G_UNICODE_NOT_PRESENT_OFFSET, 1171 },
+  { 0x1d692, G_UNICODE_NOT_PRESENT_OFFSET, 4943 },
+  { 0x1d693, G_UNICODE_NOT_PRESENT_OFFSET, 1176 },
+  { 0x1d694, G_UNICODE_NOT_PRESENT_OFFSET, 5853 },
+  { 0x1d695, G_UNICODE_NOT_PRESENT_OFFSET, 1220 },
+  { 0x1d696, G_UNICODE_NOT_PRESENT_OFFSET, 5230 },
+  { 0x1d697, G_UNICODE_NOT_PRESENT_OFFSET, 4969 },
+  { 0x1d698, G_UNICODE_NOT_PRESENT_OFFSET, 29 },
+  { 0x1d699, G_UNICODE_NOT_PRESENT_OFFSET, 5855 },
+  { 0x1d69a, G_UNICODE_NOT_PRESENT_OFFSET, 5857 },
+  { 0x1d69b, G_UNICODE_NOT_PRESENT_OFFSET, 1178 },
+  { 0x1d69c, G_UNICODE_NOT_PRESENT_OFFSET, 711 },
+  { 0x1d69d, G_UNICODE_NOT_PRESENT_OFFSET, 5859 },
+  { 0x1d69e, G_UNICODE_NOT_PRESENT_OFFSET, 5861 },
+  { 0x1d69f, G_UNICODE_NOT_PRESENT_OFFSET, 5204 },
+  { 0x1d6a0, G_UNICODE_NOT_PRESENT_OFFSET, 1189 },
+  { 0x1d6a1, G_UNICODE_NOT_PRESENT_OFFSET, 1222 },
+  { 0x1d6a2, G_UNICODE_NOT_PRESENT_OFFSET, 1191 },
+  { 0x1d6a3, G_UNICODE_NOT_PRESENT_OFFSET, 5863 },
+  { 0x1d6a8, G_UNICODE_NOT_PRESENT_OFFSET, 14361 },
+  { 0x1d6a9, G_UNICODE_NOT_PRESENT_OFFSET, 14364 },
+  { 0x1d6aa, G_UNICODE_NOT_PRESENT_OFFSET, 5067 },
+  { 0x1d6ab, G_UNICODE_NOT_PRESENT_OFFSET, 14367 },
+  { 0x1d6ac, G_UNICODE_NOT_PRESENT_OFFSET, 14370 },
+  { 0x1d6ad, G_UNICODE_NOT_PRESENT_OFFSET, 14373 },
+  { 0x1d6ae, G_UNICODE_NOT_PRESENT_OFFSET, 14376 },
+  { 0x1d6af, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d6b0, G_UNICODE_NOT_PRESENT_OFFSET, 14379 },
+  { 0x1d6b1, G_UNICODE_NOT_PRESENT_OFFSET, 14382 },
+  { 0x1d6b2, G_UNICODE_NOT_PRESENT_OFFSET, 14385 },
+  { 0x1d6b3, G_UNICODE_NOT_PRESENT_OFFSET, 14388 },
+  { 0x1d6b4, G_UNICODE_NOT_PRESENT_OFFSET, 14391 },
+  { 0x1d6b5, G_UNICODE_NOT_PRESENT_OFFSET, 14394 },
+  { 0x1d6b6, G_UNICODE_NOT_PRESENT_OFFSET, 14397 },
+  { 0x1d6b7, G_UNICODE_NOT_PRESENT_OFFSET, 5070 },
+  { 0x1d6b8, G_UNICODE_NOT_PRESENT_OFFSET, 14400 },
+  { 0x1d6b9, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d6ba, G_UNICODE_NOT_PRESENT_OFFSET, 14403 },
+  { 0x1d6bb, G_UNICODE_NOT_PRESENT_OFFSET, 14406 },
+  { 0x1d6bc, G_UNICODE_NOT_PRESENT_OFFSET, 1374 },
+  { 0x1d6bd, G_UNICODE_NOT_PRESENT_OFFSET, 14409 },
+  { 0x1d6be, G_UNICODE_NOT_PRESENT_OFFSET, 14412 },
+  { 0x1d6bf, G_UNICODE_NOT_PRESENT_OFFSET, 14415 },
+  { 0x1d6c0, G_UNICODE_NOT_PRESENT_OFFSET, 5037 },
+  { 0x1d6c1, G_UNICODE_NOT_PRESENT_OFFSET, 14418 },
+  { 0x1d6c2, G_UNICODE_NOT_PRESENT_OFFSET, 14422 },
+  { 0x1d6c3, G_UNICODE_NOT_PRESENT_OFFSET, 1368 },
+  { 0x1d6c4, G_UNICODE_NOT_PRESENT_OFFSET, 5064 },
+  { 0x1d6c5, G_UNICODE_NOT_PRESENT_OFFSET, 14425 },
+  { 0x1d6c6, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d6c7, G_UNICODE_NOT_PRESENT_OFFSET, 14428 },
+  { 0x1d6c8, G_UNICODE_NOT_PRESENT_OFFSET, 14431 },
+  { 0x1d6c9, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d6ca, G_UNICODE_NOT_PRESENT_OFFSET, 4548 },
+  { 0x1d6cb, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d6cc, G_UNICODE_NOT_PRESENT_OFFSET, 14434 },
+  { 0x1d6cd, G_UNICODE_NOT_PRESENT_OFFSET, 20 },
+  { 0x1d6ce, G_UNICODE_NOT_PRESENT_OFFSET, 14437 },
+  { 0x1d6cf, G_UNICODE_NOT_PRESENT_OFFSET, 14440 },
+  { 0x1d6d0, G_UNICODE_NOT_PRESENT_OFFSET, 14443 },
+  { 0x1d6d1, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d6d2, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d6d3, G_UNICODE_NOT_PRESENT_OFFSET, 1399 },
+  { 0x1d6d4, G_UNICODE_NOT_PRESENT_OFFSET, 14446 },
+  { 0x1d6d5, G_UNICODE_NOT_PRESENT_OFFSET, 14449 },
+  { 0x1d6d6, G_UNICODE_NOT_PRESENT_OFFSET, 14452 },
+  { 0x1d6d7, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d6d8, G_UNICODE_NOT_PRESENT_OFFSET, 14455 },
+  { 0x1d6d9, G_UNICODE_NOT_PRESENT_OFFSET, 14458 },
+  { 0x1d6da, G_UNICODE_NOT_PRESENT_OFFSET, 14461 },
+  { 0x1d6db, G_UNICODE_NOT_PRESENT_OFFSET, 14464 },
+  { 0x1d6dc, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d6dd, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d6de, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d6df, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d6e0, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d6e1, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d6e2, G_UNICODE_NOT_PRESENT_OFFSET, 14361 },
+  { 0x1d6e3, G_UNICODE_NOT_PRESENT_OFFSET, 14364 },
+  { 0x1d6e4, G_UNICODE_NOT_PRESENT_OFFSET, 5067 },
+  { 0x1d6e5, G_UNICODE_NOT_PRESENT_OFFSET, 14367 },
+  { 0x1d6e6, G_UNICODE_NOT_PRESENT_OFFSET, 14370 },
+  { 0x1d6e7, G_UNICODE_NOT_PRESENT_OFFSET, 14373 },
+  { 0x1d6e8, G_UNICODE_NOT_PRESENT_OFFSET, 14376 },
+  { 0x1d6e9, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d6ea, G_UNICODE_NOT_PRESENT_OFFSET, 14379 },
+  { 0x1d6eb, G_UNICODE_NOT_PRESENT_OFFSET, 14382 },
+  { 0x1d6ec, G_UNICODE_NOT_PRESENT_OFFSET, 14385 },
+  { 0x1d6ed, G_UNICODE_NOT_PRESENT_OFFSET, 14388 },
+  { 0x1d6ee, G_UNICODE_NOT_PRESENT_OFFSET, 14391 },
+  { 0x1d6ef, G_UNICODE_NOT_PRESENT_OFFSET, 14394 },
+  { 0x1d6f0, G_UNICODE_NOT_PRESENT_OFFSET, 14397 },
+  { 0x1d6f1, G_UNICODE_NOT_PRESENT_OFFSET, 5070 },
+  { 0x1d6f2, G_UNICODE_NOT_PRESENT_OFFSET, 14400 },
+  { 0x1d6f3, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d6f4, G_UNICODE_NOT_PRESENT_OFFSET, 14403 },
+  { 0x1d6f5, G_UNICODE_NOT_PRESENT_OFFSET, 14406 },
+  { 0x1d6f6, G_UNICODE_NOT_PRESENT_OFFSET, 1374 },
+  { 0x1d6f7, G_UNICODE_NOT_PRESENT_OFFSET, 14409 },
+  { 0x1d6f8, G_UNICODE_NOT_PRESENT_OFFSET, 14412 },
+  { 0x1d6f9, G_UNICODE_NOT_PRESENT_OFFSET, 14415 },
+  { 0x1d6fa, G_UNICODE_NOT_PRESENT_OFFSET, 5037 },
+  { 0x1d6fb, G_UNICODE_NOT_PRESENT_OFFSET, 14418 },
+  { 0x1d6fc, G_UNICODE_NOT_PRESENT_OFFSET, 14422 },
+  { 0x1d6fd, G_UNICODE_NOT_PRESENT_OFFSET, 1368 },
+  { 0x1d6fe, G_UNICODE_NOT_PRESENT_OFFSET, 5064 },
+  { 0x1d6ff, G_UNICODE_NOT_PRESENT_OFFSET, 14425 },
+  { 0x1d700, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d701, G_UNICODE_NOT_PRESENT_OFFSET, 14428 },
+  { 0x1d702, G_UNICODE_NOT_PRESENT_OFFSET, 14431 },
+  { 0x1d703, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d704, G_UNICODE_NOT_PRESENT_OFFSET, 4548 },
+  { 0x1d705, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d706, G_UNICODE_NOT_PRESENT_OFFSET, 14434 },
+  { 0x1d707, G_UNICODE_NOT_PRESENT_OFFSET, 20 },
+  { 0x1d708, G_UNICODE_NOT_PRESENT_OFFSET, 14437 },
+  { 0x1d709, G_UNICODE_NOT_PRESENT_OFFSET, 14440 },
+  { 0x1d70a, G_UNICODE_NOT_PRESENT_OFFSET, 14443 },
+  { 0x1d70b, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d70c, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d70d, G_UNICODE_NOT_PRESENT_OFFSET, 1399 },
+  { 0x1d70e, G_UNICODE_NOT_PRESENT_OFFSET, 14446 },
+  { 0x1d70f, G_UNICODE_NOT_PRESENT_OFFSET, 14449 },
+  { 0x1d710, G_UNICODE_NOT_PRESENT_OFFSET, 14452 },
+  { 0x1d711, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d712, G_UNICODE_NOT_PRESENT_OFFSET, 14455 },
+  { 0x1d713, G_UNICODE_NOT_PRESENT_OFFSET, 14458 },
+  { 0x1d714, G_UNICODE_NOT_PRESENT_OFFSET, 14461 },
+  { 0x1d715, G_UNICODE_NOT_PRESENT_OFFSET, 14464 },
+  { 0x1d716, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d717, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d718, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d719, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d71a, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d71b, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d71c, G_UNICODE_NOT_PRESENT_OFFSET, 14361 },
+  { 0x1d71d, G_UNICODE_NOT_PRESENT_OFFSET, 14364 },
+  { 0x1d71e, G_UNICODE_NOT_PRESENT_OFFSET, 5067 },
+  { 0x1d71f, G_UNICODE_NOT_PRESENT_OFFSET, 14367 },
+  { 0x1d720, G_UNICODE_NOT_PRESENT_OFFSET, 14370 },
+  { 0x1d721, G_UNICODE_NOT_PRESENT_OFFSET, 14373 },
+  { 0x1d722, G_UNICODE_NOT_PRESENT_OFFSET, 14376 },
+  { 0x1d723, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d724, G_UNICODE_NOT_PRESENT_OFFSET, 14379 },
+  { 0x1d725, G_UNICODE_NOT_PRESENT_OFFSET, 14382 },
+  { 0x1d726, G_UNICODE_NOT_PRESENT_OFFSET, 14385 },
+  { 0x1d727, G_UNICODE_NOT_PRESENT_OFFSET, 14388 },
+  { 0x1d728, G_UNICODE_NOT_PRESENT_OFFSET, 14391 },
+  { 0x1d729, G_UNICODE_NOT_PRESENT_OFFSET, 14394 },
+  { 0x1d72a, G_UNICODE_NOT_PRESENT_OFFSET, 14397 },
+  { 0x1d72b, G_UNICODE_NOT_PRESENT_OFFSET, 5070 },
+  { 0x1d72c, G_UNICODE_NOT_PRESENT_OFFSET, 14400 },
+  { 0x1d72d, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d72e, G_UNICODE_NOT_PRESENT_OFFSET, 14403 },
+  { 0x1d72f, G_UNICODE_NOT_PRESENT_OFFSET, 14406 },
+  { 0x1d730, G_UNICODE_NOT_PRESENT_OFFSET, 1374 },
+  { 0x1d731, G_UNICODE_NOT_PRESENT_OFFSET, 14409 },
+  { 0x1d732, G_UNICODE_NOT_PRESENT_OFFSET, 14412 },
+  { 0x1d733, G_UNICODE_NOT_PRESENT_OFFSET, 14415 },
+  { 0x1d734, G_UNICODE_NOT_PRESENT_OFFSET, 5037 },
+  { 0x1d735, G_UNICODE_NOT_PRESENT_OFFSET, 14418 },
+  { 0x1d736, G_UNICODE_NOT_PRESENT_OFFSET, 14422 },
+  { 0x1d737, G_UNICODE_NOT_PRESENT_OFFSET, 1368 },
+  { 0x1d738, G_UNICODE_NOT_PRESENT_OFFSET, 5064 },
+  { 0x1d739, G_UNICODE_NOT_PRESENT_OFFSET, 14425 },
+  { 0x1d73a, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d73b, G_UNICODE_NOT_PRESENT_OFFSET, 14428 },
+  { 0x1d73c, G_UNICODE_NOT_PRESENT_OFFSET, 14431 },
+  { 0x1d73d, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d73e, G_UNICODE_NOT_PRESENT_OFFSET, 4548 },
+  { 0x1d73f, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d740, G_UNICODE_NOT_PRESENT_OFFSET, 14434 },
+  { 0x1d741, G_UNICODE_NOT_PRESENT_OFFSET, 20 },
+  { 0x1d742, G_UNICODE_NOT_PRESENT_OFFSET, 14437 },
+  { 0x1d743, G_UNICODE_NOT_PRESENT_OFFSET, 14440 },
+  { 0x1d744, G_UNICODE_NOT_PRESENT_OFFSET, 14443 },
+  { 0x1d745, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d746, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d747, G_UNICODE_NOT_PRESENT_OFFSET, 1399 },
+  { 0x1d748, G_UNICODE_NOT_PRESENT_OFFSET, 14446 },
+  { 0x1d749, G_UNICODE_NOT_PRESENT_OFFSET, 14449 },
+  { 0x1d74a, G_UNICODE_NOT_PRESENT_OFFSET, 14452 },
+  { 0x1d74b, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d74c, G_UNICODE_NOT_PRESENT_OFFSET, 14455 },
+  { 0x1d74d, G_UNICODE_NOT_PRESENT_OFFSET, 14458 },
+  { 0x1d74e, G_UNICODE_NOT_PRESENT_OFFSET, 14461 },
+  { 0x1d74f, G_UNICODE_NOT_PRESENT_OFFSET, 14464 },
+  { 0x1d750, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d751, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d752, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d753, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d754, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d755, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d756, G_UNICODE_NOT_PRESENT_OFFSET, 14361 },
+  { 0x1d757, G_UNICODE_NOT_PRESENT_OFFSET, 14364 },
+  { 0x1d758, G_UNICODE_NOT_PRESENT_OFFSET, 5067 },
+  { 0x1d759, G_UNICODE_NOT_PRESENT_OFFSET, 14367 },
+  { 0x1d75a, G_UNICODE_NOT_PRESENT_OFFSET, 14370 },
+  { 0x1d75b, G_UNICODE_NOT_PRESENT_OFFSET, 14373 },
+  { 0x1d75c, G_UNICODE_NOT_PRESENT_OFFSET, 14376 },
+  { 0x1d75d, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d75e, G_UNICODE_NOT_PRESENT_OFFSET, 14379 },
+  { 0x1d75f, G_UNICODE_NOT_PRESENT_OFFSET, 14382 },
+  { 0x1d760, G_UNICODE_NOT_PRESENT_OFFSET, 14385 },
+  { 0x1d761, G_UNICODE_NOT_PRESENT_OFFSET, 14388 },
+  { 0x1d762, G_UNICODE_NOT_PRESENT_OFFSET, 14391 },
+  { 0x1d763, G_UNICODE_NOT_PRESENT_OFFSET, 14394 },
+  { 0x1d764, G_UNICODE_NOT_PRESENT_OFFSET, 14397 },
+  { 0x1d765, G_UNICODE_NOT_PRESENT_OFFSET, 5070 },
+  { 0x1d766, G_UNICODE_NOT_PRESENT_OFFSET, 14400 },
+  { 0x1d767, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d768, G_UNICODE_NOT_PRESENT_OFFSET, 14403 },
+  { 0x1d769, G_UNICODE_NOT_PRESENT_OFFSET, 14406 },
+  { 0x1d76a, G_UNICODE_NOT_PRESENT_OFFSET, 1374 },
+  { 0x1d76b, G_UNICODE_NOT_PRESENT_OFFSET, 14409 },
+  { 0x1d76c, G_UNICODE_NOT_PRESENT_OFFSET, 14412 },
+  { 0x1d76d, G_UNICODE_NOT_PRESENT_OFFSET, 14415 },
+  { 0x1d76e, G_UNICODE_NOT_PRESENT_OFFSET, 5037 },
+  { 0x1d76f, G_UNICODE_NOT_PRESENT_OFFSET, 14418 },
+  { 0x1d770, G_UNICODE_NOT_PRESENT_OFFSET, 14422 },
+  { 0x1d771, G_UNICODE_NOT_PRESENT_OFFSET, 1368 },
+  { 0x1d772, G_UNICODE_NOT_PRESENT_OFFSET, 5064 },
+  { 0x1d773, G_UNICODE_NOT_PRESENT_OFFSET, 14425 },
+  { 0x1d774, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d775, G_UNICODE_NOT_PRESENT_OFFSET, 14428 },
+  { 0x1d776, G_UNICODE_NOT_PRESENT_OFFSET, 14431 },
+  { 0x1d777, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d778, G_UNICODE_NOT_PRESENT_OFFSET, 4548 },
+  { 0x1d779, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d77a, G_UNICODE_NOT_PRESENT_OFFSET, 14434 },
+  { 0x1d77b, G_UNICODE_NOT_PRESENT_OFFSET, 20 },
+  { 0x1d77c, G_UNICODE_NOT_PRESENT_OFFSET, 14437 },
+  { 0x1d77d, G_UNICODE_NOT_PRESENT_OFFSET, 14440 },
+  { 0x1d77e, G_UNICODE_NOT_PRESENT_OFFSET, 14443 },
+  { 0x1d77f, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d780, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d781, G_UNICODE_NOT_PRESENT_OFFSET, 1399 },
+  { 0x1d782, G_UNICODE_NOT_PRESENT_OFFSET, 14446 },
+  { 0x1d783, G_UNICODE_NOT_PRESENT_OFFSET, 14449 },
+  { 0x1d784, G_UNICODE_NOT_PRESENT_OFFSET, 14452 },
+  { 0x1d785, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d786, G_UNICODE_NOT_PRESENT_OFFSET, 14455 },
+  { 0x1d787, G_UNICODE_NOT_PRESENT_OFFSET, 14458 },
+  { 0x1d788, G_UNICODE_NOT_PRESENT_OFFSET, 14461 },
+  { 0x1d789, G_UNICODE_NOT_PRESENT_OFFSET, 14464 },
+  { 0x1d78a, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d78b, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d78c, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d78d, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d78e, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d78f, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d790, G_UNICODE_NOT_PRESENT_OFFSET, 14361 },
+  { 0x1d791, G_UNICODE_NOT_PRESENT_OFFSET, 14364 },
+  { 0x1d792, G_UNICODE_NOT_PRESENT_OFFSET, 5067 },
+  { 0x1d793, G_UNICODE_NOT_PRESENT_OFFSET, 14367 },
+  { 0x1d794, G_UNICODE_NOT_PRESENT_OFFSET, 14370 },
+  { 0x1d795, G_UNICODE_NOT_PRESENT_OFFSET, 14373 },
+  { 0x1d796, G_UNICODE_NOT_PRESENT_OFFSET, 14376 },
+  { 0x1d797, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d798, G_UNICODE_NOT_PRESENT_OFFSET, 14379 },
+  { 0x1d799, G_UNICODE_NOT_PRESENT_OFFSET, 14382 },
+  { 0x1d79a, G_UNICODE_NOT_PRESENT_OFFSET, 14385 },
+  { 0x1d79b, G_UNICODE_NOT_PRESENT_OFFSET, 14388 },
+  { 0x1d79c, G_UNICODE_NOT_PRESENT_OFFSET, 14391 },
+  { 0x1d79d, G_UNICODE_NOT_PRESENT_OFFSET, 14394 },
+  { 0x1d79e, G_UNICODE_NOT_PRESENT_OFFSET, 14397 },
+  { 0x1d79f, G_UNICODE_NOT_PRESENT_OFFSET, 5070 },
+  { 0x1d7a0, G_UNICODE_NOT_PRESENT_OFFSET, 14400 },
+  { 0x1d7a1, G_UNICODE_NOT_PRESENT_OFFSET, 1402 },
+  { 0x1d7a2, G_UNICODE_NOT_PRESENT_OFFSET, 14403 },
+  { 0x1d7a3, G_UNICODE_NOT_PRESENT_OFFSET, 14406 },
+  { 0x1d7a4, G_UNICODE_NOT_PRESENT_OFFSET, 1374 },
+  { 0x1d7a5, G_UNICODE_NOT_PRESENT_OFFSET, 14409 },
+  { 0x1d7a6, G_UNICODE_NOT_PRESENT_OFFSET, 14412 },
+  { 0x1d7a7, G_UNICODE_NOT_PRESENT_OFFSET, 14415 },
+  { 0x1d7a8, G_UNICODE_NOT_PRESENT_OFFSET, 5037 },
+  { 0x1d7a9, G_UNICODE_NOT_PRESENT_OFFSET, 14418 },
+  { 0x1d7aa, G_UNICODE_NOT_PRESENT_OFFSET, 14422 },
+  { 0x1d7ab, G_UNICODE_NOT_PRESENT_OFFSET, 1368 },
+  { 0x1d7ac, G_UNICODE_NOT_PRESENT_OFFSET, 5064 },
+  { 0x1d7ad, G_UNICODE_NOT_PRESENT_OFFSET, 14425 },
+  { 0x1d7ae, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d7af, G_UNICODE_NOT_PRESENT_OFFSET, 14428 },
+  { 0x1d7b0, G_UNICODE_NOT_PRESENT_OFFSET, 14431 },
+  { 0x1d7b1, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d7b2, G_UNICODE_NOT_PRESENT_OFFSET, 4548 },
+  { 0x1d7b3, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d7b4, G_UNICODE_NOT_PRESENT_OFFSET, 14434 },
+  { 0x1d7b5, G_UNICODE_NOT_PRESENT_OFFSET, 20 },
+  { 0x1d7b6, G_UNICODE_NOT_PRESENT_OFFSET, 14437 },
+  { 0x1d7b7, G_UNICODE_NOT_PRESENT_OFFSET, 14440 },
+  { 0x1d7b8, G_UNICODE_NOT_PRESENT_OFFSET, 14443 },
+  { 0x1d7b9, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d7ba, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d7bb, G_UNICODE_NOT_PRESENT_OFFSET, 1399 },
+  { 0x1d7bc, G_UNICODE_NOT_PRESENT_OFFSET, 14446 },
+  { 0x1d7bd, G_UNICODE_NOT_PRESENT_OFFSET, 14449 },
+  { 0x1d7be, G_UNICODE_NOT_PRESENT_OFFSET, 14452 },
+  { 0x1d7bf, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d7c0, G_UNICODE_NOT_PRESENT_OFFSET, 14455 },
+  { 0x1d7c1, G_UNICODE_NOT_PRESENT_OFFSET, 14458 },
+  { 0x1d7c2, G_UNICODE_NOT_PRESENT_OFFSET, 14461 },
+  { 0x1d7c3, G_UNICODE_NOT_PRESENT_OFFSET, 14464 },
+  { 0x1d7c4, G_UNICODE_NOT_PRESENT_OFFSET, 1405 },
+  { 0x1d7c5, G_UNICODE_NOT_PRESENT_OFFSET, 1371 },
+  { 0x1d7c6, G_UNICODE_NOT_PRESENT_OFFSET, 1393 },
+  { 0x1d7c7, G_UNICODE_NOT_PRESENT_OFFSET, 1387 },
+  { 0x1d7c8, G_UNICODE_NOT_PRESENT_OFFSET, 1396 },
+  { 0x1d7c9, G_UNICODE_NOT_PRESENT_OFFSET, 1390 },
+  { 0x1d7ce, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x1d7cf, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x1d7d0, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x1d7d1, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x1d7d2, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x1d7d3, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x1d7d4, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x1d7d5, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x1d7d6, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x1d7d7, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x1d7d8, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x1d7d9, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x1d7da, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x1d7db, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x1d7dc, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x1d7dd, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x1d7de, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x1d7df, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x1d7e0, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x1d7e1, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x1d7e2, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x1d7e3, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x1d7e4, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x1d7e5, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x1d7e6, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x1d7e7, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x1d7e8, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x1d7e9, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x1d7ea, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x1d7eb, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x1d7ec, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x1d7ed, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x1d7ee, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x1d7ef, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x1d7f0, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x1d7f1, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x1d7f2, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x1d7f3, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x1d7f4, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x1d7f5, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x1d7f6, G_UNICODE_NOT_PRESENT_OFFSET, 4941 },
+  { 0x1d7f7, G_UNICODE_NOT_PRESENT_OFFSET, 27 },
+  { 0x1d7f8, G_UNICODE_NOT_PRESENT_OFFSET, 12 },
+  { 0x1d7f9, G_UNICODE_NOT_PRESENT_OFFSET, 14 },
+  { 0x1d7fa, G_UNICODE_NOT_PRESENT_OFFSET, 4945 },
+  { 0x1d7fb, G_UNICODE_NOT_PRESENT_OFFSET, 4947 },
+  { 0x1d7fc, G_UNICODE_NOT_PRESENT_OFFSET, 4949 },
+  { 0x1d7fd, G_UNICODE_NOT_PRESENT_OFFSET, 4951 },
+  { 0x1d7fe, G_UNICODE_NOT_PRESENT_OFFSET, 4953 },
+  { 0x1d7ff, G_UNICODE_NOT_PRESENT_OFFSET, 4955 },
+  { 0x2f800, 14468, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f801, 14472, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f802, 14476, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f803, 14480, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f804, 14485, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f805, 11545, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f806, 14489, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f807, 14493, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f808, 14497, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f809, 14501, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f80a, 11549, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f80b, 14505, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f80c, 14509, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f80d, 14513, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f80e, 11553, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f80f, 14518, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f810, 14522, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f811, 14526, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f812, 14530, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f813, 14535, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f814, 14539, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f815, 14543, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f816, 14547, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f817, 14552, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f818, 14556, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f819, 14560, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f81a, 14564, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f81b, 14568, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f81c, 14572, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f81d, 5967, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f81e, 14577, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f81f, 14581, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f820, 14585, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f821, 14589, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f822, 14593, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f823, 14597, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f824, 14601, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f825, 14605, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f826, 11557, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f827, 11561, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f828, 14609, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f829, 14613, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f82a, 14617, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f82b, 10837, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f82c, 14621, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f82d, 11565, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f82e, 14625, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f82f, 14629, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f830, 14633, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f831, 14637, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f832, 14637, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f833, 14637, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f834, 14641, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f835, 14646, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f836, 14650, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f837, 14654, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f838, 14658, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f839, 14663, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f83a, 14667, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f83b, 14671, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f83c, 14675, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f83d, 14679, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f83e, 14683, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f83f, 14687, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f840, 14691, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f841, 14695, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f842, 14699, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f843, 14703, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f844, 14707, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f845, 14711, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f846, 14711, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f847, 14715, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f848, 14719, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f849, 14723, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f84a, 14727, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f84b, 14731, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f84c, 11573, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f84d, 14735, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f84e, 14739, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f84f, 14743, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f850, 11421, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f851, 14747, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f852, 14751, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f853, 14755, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f854, 14759, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f855, 14763, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f856, 14767, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f857, 14771, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f858, 14775, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f859, 14779, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f85a, 14784, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f85b, 14788, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f85c, 14792, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f85d, 14796, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f85e, 14800, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f85f, 14804, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f860, 14808, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f861, 14813, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f862, 14818, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f863, 14822, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f864, 14826, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f865, 14830, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f866, 14834, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f867, 14838, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f868, 14842, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f869, 14847, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f86a, 14851, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f86b, 14851, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f86c, 14855, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f86d, 14860, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f86e, 14864, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f86f, 10821, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f870, 14868, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f871, 14872, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f872, 14877, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f873, 14881, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f874, 14885, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f875, 6071, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f876, 14889, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f877, 14893, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f878, 6079, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f879, 14897, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f87a, 14901, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f87b, 14905, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f87c, 14910, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f87d, 14914, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f87e, 14919, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f87f, 14923, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f880, 14927, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f881, 14931, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f882, 14935, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f883, 14939, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f884, 14943, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f885, 14947, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f886, 14951, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f887, 14955, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f888, 14959, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f889, 14963, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f88a, 14968, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f88b, 14972, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f88c, 14976, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f88d, 14980, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f88e, 10613, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f88f, 14984, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f890, 6119, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f891, 14989, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f892, 14989, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f893, 14994, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f894, 14998, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f895, 14998, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f896, 15002, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f897, 15006, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f898, 15011, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f899, 15016, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f89a, 15020, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f89b, 15024, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f89c, 15028, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f89d, 15032, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f89e, 15036, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f89f, 15040, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a0, 15044, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a1, 15048, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a2, 15052, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a3, 11593, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a4, 15056, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a5, 15061, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a6, 15065, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a7, 15069, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a8, 15073, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8a9, 15069, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8aa, 15077, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ab, 11601, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ac, 15081, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ad, 15085, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ae, 15089, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8af, 15093, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b0, 11605, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b1, 10505, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b2, 15097, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b3, 15101, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b4, 15105, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b5, 15109, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b6, 15113, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b7, 15117, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b8, 15121, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8b9, 15126, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ba, 15130, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8bb, 15134, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8bc, 15138, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8bd, 15142, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8be, 15146, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8bf, 15151, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c0, 15155, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c1, 15159, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c2, 15163, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c3, 15167, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c4, 15171, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c5, 15175, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c6, 15179, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c7, 15183, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c8, 11609, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8c9, 15187, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ca, 15191, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8cb, 15196, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8cc, 15200, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8cd, 15204, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ce, 15208, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8cf, 11617, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d0, 15212, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d1, 15216, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d2, 15220, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d3, 15224, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d4, 15228, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d5, 15232, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d6, 15236, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d7, 15240, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d8, 10617, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8d9, 15244, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8da, 15248, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8db, 15252, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8dc, 15256, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8dd, 15260, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8de, 15265, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8df, 15269, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e0, 15273, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e1, 15277, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e2, 11621, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e3, 15281, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e4, 15286, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e5, 15290, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e6, 15294, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e7, 15298, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e8, 15302, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8e9, 15306, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ea, 15310, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8eb, 15314, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ec, 15318, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ed, 15323, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ee, 15327, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ef, 15331, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f0, 15335, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f1, 15340, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f2, 15344, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f3, 15348, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f4, 15352, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f5, 10889, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f6, 15356, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f7, 15360, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f8, 15365, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8f9, 15370, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8fa, 15375, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8fb, 15379, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8fc, 15384, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8fd, 15388, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8fe, 15392, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f8ff, 15396, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f900, 15400, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f901, 11625, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f902, 11221, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f903, 15404, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f904, 15408, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f905, 15412, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f906, 15416, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f907, 15421, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f908, 15425, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f909, 15429, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f90a, 15433, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f90b, 15437, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f90c, 15441, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f90d, 15445, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f90e, 15450, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f90f, 15454, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f910, 15458, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f911, 15463, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f912, 15468, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f913, 15472, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f914, 15476, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f915, 15480, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f916, 15484, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f917, 15488, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f918, 15492, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f919, 15496, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f91a, 15500, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f91b, 15504, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f91c, 15509, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f91d, 15513, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f91e, 15518, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f91f, 15522, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f920, 15526, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f921, 15530, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f922, 15534, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f923, 15538, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f924, 15543, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f925, 15547, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f926, 15551, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f927, 15556, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f928, 15561, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f929, 15565, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f92a, 15569, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f92b, 15573, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f92c, 15577, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f92d, 15577, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f92e, 15581, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f92f, 15585, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f930, 15589, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f931, 15593, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f932, 15597, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f933, 15601, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f934, 15605, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f935, 15609, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f936, 15614, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f937, 15618, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f938, 10833, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f939, 15623, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f93a, 15628, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f93b, 15632, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f93c, 15637, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f93d, 15642, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f93e, 15647, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f93f, 15651, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f940, 15655, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f941, 15659, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f942, 15664, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f943, 15669, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f944, 15674, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f945, 15679, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f946, 15683, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f947, 15683, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f948, 15687, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f949, 15691, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f94a, 15695, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f94b, 15699, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f94c, 15703, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f94d, 15707, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f94e, 15712, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f94f, 10685, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f950, 15716, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f951, 15720, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f952, 15724, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f953, 11665, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f954, 15729, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f955, 15734, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f956, 11501, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f957, 15739, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f958, 15743, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f959, 11677, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f95a, 15747, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f95b, 15751, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f95c, 15755, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f95d, 15760, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f95e, 15760, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f95f, 15765, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f960, 15769, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f961, 15773, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f962, 15778, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f963, 15782, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f964, 15786, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f965, 15790, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f966, 15795, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f967, 15799, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f968, 15803, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f969, 15807, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f96a, 15811, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f96b, 15815, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f96c, 15820, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f96d, 15824, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f96e, 15828, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f96f, 15832, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f970, 15836, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f971, 15840, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f972, 15844, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f973, 15849, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f974, 15854, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f975, 15858, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f976, 15863, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f977, 15867, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f978, 15872, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f979, 15876, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f97a, 11701, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f97b, 15880, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f97c, 15885, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f97d, 15890, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f97e, 15894, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f97f, 15899, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f980, 15903, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f981, 15908, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f982, 15912, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f983, 15916, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f984, 15920, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f985, 15924, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f986, 15928, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f987, 15932, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f988, 15937, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f989, 15942, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f98a, 15947, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f98b, 14994, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f98c, 15952, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f98d, 15956, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f98e, 15960, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f98f, 15964, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f990, 15968, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f991, 15972, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f992, 15976, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f993, 15980, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f994, 15984, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f995, 15988, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f996, 15992, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f997, 15996, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f998, 10901, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f999, 16001, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f99a, 16005, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f99b, 16009, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f99c, 16013, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f99d, 16017, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f99e, 16021, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f99f, 11713, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a0, 16025, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a1, 16029, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a2, 16033, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a3, 16037, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a4, 16041, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a5, 16046, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a6, 16051, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a7, 16056, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a8, 16060, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9a9, 16064, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9aa, 16068, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ab, 16072, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ac, 16077, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ad, 16081, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ae, 16086, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9af, 16090, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b0, 16094, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b1, 16099, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b2, 16104, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b3, 16108, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b4, 10665, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b5, 16112, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b6, 16116, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b7, 16120, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b8, 16124, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9b9, 16128, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ba, 16132, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9bb, 16136, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9bc, 16140, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9bd, 16144, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9be, 16148, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9bf, 16152, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c0, 16156, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c1, 16160, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c2, 16164, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c3, 16168, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c4, 6479, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c5, 16172, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c6, 16177, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c7, 16181, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c8, 16185, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9c9, 16189, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ca, 16193, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9cb, 16197, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9cc, 16202, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9cd, 16207, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ce, 16211, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9cf, 16215, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d0, 16219, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d1, 16223, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d2, 6507, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d3, 16227, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d4, 16232, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d5, 16236, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d6, 16240, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d7, 16244, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d8, 16248, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9d9, 16253, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9da, 16258, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9db, 16262, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9dc, 16266, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9dd, 16270, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9de, 16275, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9df, 16279, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e0, 16283, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e1, 16288, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e2, 16293, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e3, 16297, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e4, 16301, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e5, 16305, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e6, 16310, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e7, 16314, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e8, 16318, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9e9, 16322, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ea, 16326, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9eb, 16330, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ec, 16334, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ed, 16338, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ee, 16343, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ef, 16347, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f0, 16351, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f1, 16355, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f2, 16360, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f3, 16364, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f4, 16368, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f5, 16372, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f6, 16376, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f7, 16381, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f8, 16386, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9f9, 16390, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9fa, 16394, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9fb, 16398, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9fc, 16403, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9fd, 16407, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9fe, 16412, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2f9ff, 16412, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa00, 16416, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa01, 16420, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa02, 16425, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa03, 16429, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa04, 16433, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa05, 16437, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa06, 16441, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa07, 16445, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa08, 16449, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa09, 16453, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa0a, 16458, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa0b, 16462, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa0c, 16466, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa0d, 16470, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa0e, 16474, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa0f, 16478, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa10, 16482, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa11, 16487, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa12, 16491, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa13, 16496, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa14, 16501, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa15, 6699, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa16, 16506, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa17, 6715, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa18, 16510, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa19, 16514, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa1a, 16518, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa1b, 16522, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa1c, 6735, G_UNICODE_NOT_PRESENT_OFFSET },
+  { 0x2fa1d, 16526, G_UNICODE_NOT_PRESENT_OFFSET }
+};
+
+static const gchar decomp_expansion_string[] = 
+  "\x20\0" /* offset 0 */
+  "\x20\xcc\x88\0" /* offset 2 */
+  "\x61\0" /* offset 6 */
+  "\x20\xcc\x84\0" /* offset 8 */
+  "\x32\0" /* offset 12 */
+  "\x33\0" /* offset 14 */
+  "\x20\xcc\x81\0" /* offset 16 */
+  "\xce\xbc\0" /* offset 20 */
+  "\x20\xcc\xa7\0" /* offset 23 */
+  "\x31\0" /* offset 27 */
+  "\x6f\0" /* offset 29 */
+  "\x31\xe2\x81\x84\x34\0" /* offset 31 */
+  "\x31\xe2\x81\x84\x32\0" /* offset 37 */
+  "\x33\xe2\x81\x84\x34\0" /* offset 43 */
+  "\x41\xcc\x80\0" /* offset 49 */
+  "\x41\xcc\x81\0" /* offset 53 */
+  "\x41\xcc\x82\0" /* offset 57 */
+  "\x41\xcc\x83\0" /* offset 61 */
+  "\x41\xcc\x88\0" /* offset 65 */
+  "\x41\xcc\x8a\0" /* offset 69 */
+  "\x43\xcc\xa7\0" /* offset 73 */
+  "\x45\xcc\x80\0" /* offset 77 */
+  "\x45\xcc\x81\0" /* offset 81 */
+  "\x45\xcc\x82\0" /* offset 85 */
+  "\x45\xcc\x88\0" /* offset 89 */
+  "\x49\xcc\x80\0" /* offset 93 */
+  "\x49\xcc\x81\0" /* offset 97 */
+  "\x49\xcc\x82\0" /* offset 101 */
+  "\x49\xcc\x88\0" /* offset 105 */
+  "\x4e\xcc\x83\0" /* offset 109 */
+  "\x4f\xcc\x80\0" /* offset 113 */
+  "\x4f\xcc\x81\0" /* offset 117 */
+  "\x4f\xcc\x82\0" /* offset 121 */
+  "\x4f\xcc\x83\0" /* offset 125 */
+  "\x4f\xcc\x88\0" /* offset 129 */
+  "\x55\xcc\x80\0" /* offset 133 */
+  "\x55\xcc\x81\0" /* offset 137 */
+  "\x55\xcc\x82\0" /* offset 141 */
+  "\x55\xcc\x88\0" /* offset 145 */
+  "\x59\xcc\x81\0" /* offset 149 */
+  "\x61\xcc\x80\0" /* offset 153 */
+  "\x61\xcc\x81\0" /* offset 157 */
+  "\x61\xcc\x82\0" /* offset 161 */
+  "\x61\xcc\x83\0" /* offset 165 */
+  "\x61\xcc\x88\0" /* offset 169 */
+  "\x61\xcc\x8a\0" /* offset 173 */
+  "\x63\xcc\xa7\0" /* offset 177 */
+  "\x65\xcc\x80\0" /* offset 181 */
+  "\x65\xcc\x81\0" /* offset 185 */
+  "\x65\xcc\x82\0" /* offset 189 */
+  "\x65\xcc\x88\0" /* offset 193 */
+  "\x69\xcc\x80\0" /* offset 197 */
+  "\x69\xcc\x81\0" /* offset 201 */
+  "\x69\xcc\x82\0" /* offset 205 */
+  "\x69\xcc\x88\0" /* offset 209 */
+  "\x6e\xcc\x83\0" /* offset 213 */
+  "\x6f\xcc\x80\0" /* offset 217 */
+  "\x6f\xcc\x81\0" /* offset 221 */
+  "\x6f\xcc\x82\0" /* offset 225 */
+  "\x6f\xcc\x83\0" /* offset 229 */
+  "\x6f\xcc\x88\0" /* offset 233 */
+  "\x75\xcc\x80\0" /* offset 237 */
+  "\x75\xcc\x81\0" /* offset 241 */
+  "\x75\xcc\x82\0" /* offset 245 */
+  "\x75\xcc\x88\0" /* offset 249 */
+  "\x79\xcc\x81\0" /* offset 253 */
+  "\x79\xcc\x88\0" /* offset 257 */
+  "\x41\xcc\x84\0" /* offset 261 */
+  "\x61\xcc\x84\0" /* offset 265 */
+  "\x41\xcc\x86\0" /* offset 269 */
+  "\x61\xcc\x86\0" /* offset 273 */
+  "\x41\xcc\xa8\0" /* offset 277 */
+  "\x61\xcc\xa8\0" /* offset 281 */
+  "\x43\xcc\x81\0" /* offset 285 */
+  "\x63\xcc\x81\0" /* offset 289 */
+  "\x43\xcc\x82\0" /* offset 293 */
+  "\x63\xcc\x82\0" /* offset 297 */
+  "\x43\xcc\x87\0" /* offset 301 */
+  "\x63\xcc\x87\0" /* offset 305 */
+  "\x43\xcc\x8c\0" /* offset 309 */
+  "\x63\xcc\x8c\0" /* offset 313 */
+  "\x44\xcc\x8c\0" /* offset 317 */
+  "\x64\xcc\x8c\0" /* offset 321 */
+  "\x45\xcc\x84\0" /* offset 325 */
+  "\x65\xcc\x84\0" /* offset 329 */
+  "\x45\xcc\x86\0" /* offset 333 */
+  "\x65\xcc\x86\0" /* offset 337 */
+  "\x45\xcc\x87\0" /* offset 341 */
+  "\x65\xcc\x87\0" /* offset 345 */
+  "\x45\xcc\xa8\0" /* offset 349 */
+  "\x65\xcc\xa8\0" /* offset 353 */
+  "\x45\xcc\x8c\0" /* offset 357 */
+  "\x65\xcc\x8c\0" /* offset 361 */
+  "\x47\xcc\x82\0" /* offset 365 */
+  "\x67\xcc\x82\0" /* offset 369 */
+  "\x47\xcc\x86\0" /* offset 373 */
+  "\x67\xcc\x86\0" /* offset 377 */
+  "\x47\xcc\x87\0" /* offset 381 */
+  "\x67\xcc\x87\0" /* offset 385 */
+  "\x47\xcc\xa7\0" /* offset 389 */
+  "\x67\xcc\xa7\0" /* offset 393 */
+  "\x48\xcc\x82\0" /* offset 397 */
+  "\x68\xcc\x82\0" /* offset 401 */
+  "\x49\xcc\x83\0" /* offset 405 */
+  "\x69\xcc\x83\0" /* offset 409 */
+  "\x49\xcc\x84\0" /* offset 413 */
+  "\x69\xcc\x84\0" /* offset 417 */
+  "\x49\xcc\x86\0" /* offset 421 */
+  "\x69\xcc\x86\0" /* offset 425 */
+  "\x49\xcc\xa8\0" /* offset 429 */
+  "\x69\xcc\xa8\0" /* offset 433 */
+  "\x49\xcc\x87\0" /* offset 437 */
+  "\x49\x4a\0" /* offset 441 */
+  "\x69\x6a\0" /* offset 444 */
+  "\x4a\xcc\x82\0" /* offset 447 */
+  "\x6a\xcc\x82\0" /* offset 451 */
+  "\x4b\xcc\xa7\0" /* offset 455 */
+  "\x6b\xcc\xa7\0" /* offset 459 */
+  "\x4c\xcc\x81\0" /* offset 463 */
+  "\x6c\xcc\x81\0" /* offset 467 */
+  "\x4c\xcc\xa7\0" /* offset 471 */
+  "\x6c\xcc\xa7\0" /* offset 475 */
+  "\x4c\xcc\x8c\0" /* offset 479 */
+  "\x6c\xcc\x8c\0" /* offset 483 */
+  "\x4c\xc2\xb7\0" /* offset 487 */
+  "\x6c\xc2\xb7\0" /* offset 491 */
+  "\x4e\xcc\x81\0" /* offset 495 */
+  "\x6e\xcc\x81\0" /* offset 499 */
+  "\x4e\xcc\xa7\0" /* offset 503 */
+  "\x6e\xcc\xa7\0" /* offset 507 */
+  "\x4e\xcc\x8c\0" /* offset 511 */
+  "\x6e\xcc\x8c\0" /* offset 515 */
+  "\xca\xbc\x6e\0" /* offset 519 */
+  "\x4f\xcc\x84\0" /* offset 523 */
+  "\x6f\xcc\x84\0" /* offset 527 */
+  "\x4f\xcc\x86\0" /* offset 531 */
+  "\x6f\xcc\x86\0" /* offset 535 */
+  "\x4f\xcc\x8b\0" /* offset 539 */
+  "\x6f\xcc\x8b\0" /* offset 543 */
+  "\x52\xcc\x81\0" /* offset 547 */
+  "\x72\xcc\x81\0" /* offset 551 */
+  "\x52\xcc\xa7\0" /* offset 555 */
+  "\x72\xcc\xa7\0" /* offset 559 */
+  "\x52\xcc\x8c\0" /* offset 563 */
+  "\x72\xcc\x8c\0" /* offset 567 */
+  "\x53\xcc\x81\0" /* offset 571 */
+  "\x73\xcc\x81\0" /* offset 575 */
+  "\x53\xcc\x82\0" /* offset 579 */
+  "\x73\xcc\x82\0" /* offset 583 */
+  "\x53\xcc\xa7\0" /* offset 587 */
+  "\x73\xcc\xa7\0" /* offset 591 */
+  "\x53\xcc\x8c\0" /* offset 595 */
+  "\x73\xcc\x8c\0" /* offset 599 */
+  "\x54\xcc\xa7\0" /* offset 603 */
+  "\x74\xcc\xa7\0" /* offset 607 */
+  "\x54\xcc\x8c\0" /* offset 611 */
+  "\x74\xcc\x8c\0" /* offset 615 */
+  "\x55\xcc\x83\0" /* offset 619 */
+  "\x75\xcc\x83\0" /* offset 623 */
+  "\x55\xcc\x84\0" /* offset 627 */
+  "\x75\xcc\x84\0" /* offset 631 */
+  "\x55\xcc\x86\0" /* offset 635 */
+  "\x75\xcc\x86\0" /* offset 639 */
+  "\x55\xcc\x8a\0" /* offset 643 */
+  "\x75\xcc\x8a\0" /* offset 647 */
+  "\x55\xcc\x8b\0" /* offset 651 */
+  "\x75\xcc\x8b\0" /* offset 655 */
+  "\x55\xcc\xa8\0" /* offset 659 */
+  "\x75\xcc\xa8\0" /* offset 663 */
+  "\x57\xcc\x82\0" /* offset 667 */
+  "\x77\xcc\x82\0" /* offset 671 */
+  "\x59\xcc\x82\0" /* offset 675 */
+  "\x79\xcc\x82\0" /* offset 679 */
+  "\x59\xcc\x88\0" /* offset 683 */
+  "\x5a\xcc\x81\0" /* offset 687 */
+  "\x7a\xcc\x81\0" /* offset 691 */
+  "\x5a\xcc\x87\0" /* offset 695 */
+  "\x7a\xcc\x87\0" /* offset 699 */
+  "\x5a\xcc\x8c\0" /* offset 703 */
+  "\x7a\xcc\x8c\0" /* offset 707 */
+  "\x73\0" /* offset 711 */
+  "\x4f\xcc\x9b\0" /* offset 713 */
+  "\x6f\xcc\x9b\0" /* offset 717 */
+  "\x55\xcc\x9b\0" /* offset 721 */
+  "\x75\xcc\x9b\0" /* offset 725 */
+  "\x44\x5a\xcc\x8c\0" /* offset 729 */
+  "\x44\x7a\xcc\x8c\0" /* offset 734 */
+  "\x64\x7a\xcc\x8c\0" /* offset 739 */
+  "\x4c\x4a\0" /* offset 744 */
+  "\x4c\x6a\0" /* offset 747 */
+  "\x6c\x6a\0" /* offset 750 */
+  "\x4e\x4a\0" /* offset 753 */
+  "\x4e\x6a\0" /* offset 756 */
+  "\x6e\x6a\0" /* offset 759 */
+  "\x41\xcc\x8c\0" /* offset 762 */
+  "\x61\xcc\x8c\0" /* offset 766 */
+  "\x49\xcc\x8c\0" /* offset 770 */
+  "\x69\xcc\x8c\0" /* offset 774 */
+  "\x4f\xcc\x8c\0" /* offset 778 */
+  "\x6f\xcc\x8c\0" /* offset 782 */
+  "\x55\xcc\x8c\0" /* offset 786 */
+  "\x75\xcc\x8c\0" /* offset 790 */
+  "\x55\xcc\x88\xcc\x84\0" /* offset 794 */
+  "\x75\xcc\x88\xcc\x84\0" /* offset 800 */
+  "\x55\xcc\x88\xcc\x81\0" /* offset 806 */
+  "\x75\xcc\x88\xcc\x81\0" /* offset 812 */
+  "\x55\xcc\x88\xcc\x8c\0" /* offset 818 */
+  "\x75\xcc\x88\xcc\x8c\0" /* offset 824 */
+  "\x55\xcc\x88\xcc\x80\0" /* offset 830 */
+  "\x75\xcc\x88\xcc\x80\0" /* offset 836 */
+  "\x41\xcc\x88\xcc\x84\0" /* offset 842 */
+  "\x61\xcc\x88\xcc\x84\0" /* offset 848 */
+  "\x41\xcc\x87\xcc\x84\0" /* offset 854 */
+  "\x61\xcc\x87\xcc\x84\0" /* offset 860 */
+  "\xc3\x86\xcc\x84\0" /* offset 866 */
+  "\xc3\xa6\xcc\x84\0" /* offset 871 */
+  "\x47\xcc\x8c\0" /* offset 876 */
+  "\x67\xcc\x8c\0" /* offset 880 */
+  "\x4b\xcc\x8c\0" /* offset 884 */
+  "\x6b\xcc\x8c\0" /* offset 888 */
+  "\x4f\xcc\xa8\0" /* offset 892 */
+  "\x6f\xcc\xa8\0" /* offset 896 */
+  "\x4f\xcc\xa8\xcc\x84\0" /* offset 900 */
+  "\x6f\xcc\xa8\xcc\x84\0" /* offset 906 */
+  "\xc6\xb7\xcc\x8c\0" /* offset 912 */
+  "\xca\x92\xcc\x8c\0" /* offset 917 */
+  "\x6a\xcc\x8c\0" /* offset 922 */
+  "\x44\x5a\0" /* offset 926 */
+  "\x44\x7a\0" /* offset 929 */
+  "\x64\x7a\0" /* offset 932 */
+  "\x47\xcc\x81\0" /* offset 935 */
+  "\x67\xcc\x81\0" /* offset 939 */
+  "\x4e\xcc\x80\0" /* offset 943 */
+  "\x6e\xcc\x80\0" /* offset 947 */
+  "\x41\xcc\x8a\xcc\x81\0" /* offset 951 */
+  "\x61\xcc\x8a\xcc\x81\0" /* offset 957 */
+  "\xc3\x86\xcc\x81\0" /* offset 963 */
+  "\xc3\xa6\xcc\x81\0" /* offset 968 */
+  "\xc3\x98\xcc\x81\0" /* offset 973 */
+  "\xc3\xb8\xcc\x81\0" /* offset 978 */
+  "\x41\xcc\x8f\0" /* offset 983 */
+  "\x61\xcc\x8f\0" /* offset 987 */
+  "\x41\xcc\x91\0" /* offset 991 */
+  "\x61\xcc\x91\0" /* offset 995 */
+  "\x45\xcc\x8f\0" /* offset 999 */
+  "\x65\xcc\x8f\0" /* offset 1003 */
+  "\x45\xcc\x91\0" /* offset 1007 */
+  "\x65\xcc\x91\0" /* offset 1011 */
+  "\x49\xcc\x8f\0" /* offset 1015 */
+  "\x69\xcc\x8f\0" /* offset 1019 */
+  "\x49\xcc\x91\0" /* offset 1023 */
+  "\x69\xcc\x91\0" /* offset 1027 */
+  "\x4f\xcc\x8f\0" /* offset 1031 */
+  "\x6f\xcc\x8f\0" /* offset 1035 */
+  "\x4f\xcc\x91\0" /* offset 1039 */
+  "\x6f\xcc\x91\0" /* offset 1043 */
+  "\x52\xcc\x8f\0" /* offset 1047 */
+  "\x72\xcc\x8f\0" /* offset 1051 */
+  "\x52\xcc\x91\0" /* offset 1055 */
+  "\x72\xcc\x91\0" /* offset 1059 */
+  "\x55\xcc\x8f\0" /* offset 1063 */
+  "\x75\xcc\x8f\0" /* offset 1067 */
+  "\x55\xcc\x91\0" /* offset 1071 */
+  "\x75\xcc\x91\0" /* offset 1075 */
+  "\x53\xcc\xa6\0" /* offset 1079 */
+  "\x73\xcc\xa6\0" /* offset 1083 */
+  "\x54\xcc\xa6\0" /* offset 1087 */
+  "\x74\xcc\xa6\0" /* offset 1091 */
+  "\x48\xcc\x8c\0" /* offset 1095 */
+  "\x68\xcc\x8c\0" /* offset 1099 */
+  "\x41\xcc\x87\0" /* offset 1103 */
+  "\x61\xcc\x87\0" /* offset 1107 */
+  "\x45\xcc\xa7\0" /* offset 1111 */
+  "\x65\xcc\xa7\0" /* offset 1115 */
+  "\x4f\xcc\x88\xcc\x84\0" /* offset 1119 */
+  "\x6f\xcc\x88\xcc\x84\0" /* offset 1125 */
+  "\x4f\xcc\x83\xcc\x84\0" /* offset 1131 */
+  "\x6f\xcc\x83\xcc\x84\0" /* offset 1137 */
+  "\x4f\xcc\x87\0" /* offset 1143 */
+  "\x6f\xcc\x87\0" /* offset 1147 */
+  "\x4f\xcc\x87\xcc\x84\0" /* offset 1151 */
+  "\x6f\xcc\x87\xcc\x84\0" /* offset 1157 */
+  "\x59\xcc\x84\0" /* offset 1163 */
+  "\x79\xcc\x84\0" /* offset 1167 */
+  "\x68\0" /* offset 1171 */
+  "\xc9\xa6\0" /* offset 1173 */
+  "\x6a\0" /* offset 1176 */
+  "\x72\0" /* offset 1178 */
+  "\xc9\xb9\0" /* offset 1180 */
+  "\xc9\xbb\0" /* offset 1183 */
+  "\xca\x81\0" /* offset 1186 */
+  "\x77\0" /* offset 1189 */
+  "\x79\0" /* offset 1191 */
+  "\x20\xcc\x86\0" /* offset 1193 */
+  "\x20\xcc\x87\0" /* offset 1197 */
+  "\x20\xcc\x8a\0" /* offset 1201 */
+  "\x20\xcc\xa8\0" /* offset 1205 */
+  "\x20\xcc\x83\0" /* offset 1209 */
+  "\x20\xcc\x8b\0" /* offset 1213 */
+  "\xc9\xa3\0" /* offset 1217 */
+  "\x6c\0" /* offset 1220 */
+  "\x78\0" /* offset 1222 */
+  "\xca\x95\0" /* offset 1224 */
+  "\xcc\x80\0" /* offset 1227 */
+  "\xcc\x81\0" /* offset 1230 */
+  "\xcc\x93\0" /* offset 1233 */
+  "\xcc\x88\xcc\x81\0" /* offset 1236 */
+  "\xca\xb9\0" /* offset 1241 */
+  "\x20\xcd\x85\0" /* offset 1244 */
+  "\x3b\0" /* offset 1248 */
+  "\xc2\xa8\xcc\x81\0" /* offset 1250 */
+  "\x20\xcc\x88\xcc\x81\0" /* offset 1255 */
+  "\xce\x91\xcc\x81\0" /* offset 1261 */
+  "\xc2\xb7\0" /* offset 1266 */
+  "\xce\x95\xcc\x81\0" /* offset 1269 */
+  "\xce\x97\xcc\x81\0" /* offset 1274 */
+  "\xce\x99\xcc\x81\0" /* offset 1279 */
+  "\xce\x9f\xcc\x81\0" /* offset 1284 */
+  "\xce\xa5\xcc\x81\0" /* offset 1289 */
+  "\xce\xa9\xcc\x81\0" /* offset 1294 */
+  "\xce\xb9\xcc\x88\xcc\x81\0" /* offset 1299 */
+  "\xce\x99\xcc\x88\0" /* offset 1306 */
+  "\xce\xa5\xcc\x88\0" /* offset 1311 */
+  "\xce\xb1\xcc\x81\0" /* offset 1316 */
+  "\xce\xb5\xcc\x81\0" /* offset 1321 */
+  "\xce\xb7\xcc\x81\0" /* offset 1326 */
+  "\xce\xb9\xcc\x81\0" /* offset 1331 */
+  "\xcf\x85\xcc\x88\xcc\x81\0" /* offset 1336 */
+  "\xce\xb9\xcc\x88\0" /* offset 1343 */
+  "\xcf\x85\xcc\x88\0" /* offset 1348 */
+  "\xce\xbf\xcc\x81\0" /* offset 1353 */
+  "\xcf\x85\xcc\x81\0" /* offset 1358 */
+  "\xcf\x89\xcc\x81\0" /* offset 1363 */
+  "\xce\xb2\0" /* offset 1368 */
+  "\xce\xb8\0" /* offset 1371 */
+  "\xce\xa5\0" /* offset 1374 */
+  "\xcf\x92\xcc\x81\0" /* offset 1377 */
+  "\xcf\x92\xcc\x88\0" /* offset 1382 */
+  "\xcf\x86\0" /* offset 1387 */
+  "\xcf\x80\0" /* offset 1390 */
+  "\xce\xba\0" /* offset 1393 */
+  "\xcf\x81\0" /* offset 1396 */
+  "\xcf\x82\0" /* offset 1399 */
+  "\xce\x98\0" /* offset 1402 */
+  "\xce\xb5\0" /* offset 1405 */
+  "\xd0\x95\xcc\x80\0" /* offset 1408 */
+  "\xd0\x95\xcc\x88\0" /* offset 1413 */
+  "\xd0\x93\xcc\x81\0" /* offset 1418 */
+  "\xd0\x86\xcc\x88\0" /* offset 1423 */
+  "\xd0\x9a\xcc\x81\0" /* offset 1428 */
+  "\xd0\x98\xcc\x80\0" /* offset 1433 */
+  "\xd0\xa3\xcc\x86\0" /* offset 1438 */
+  "\xd0\x98\xcc\x86\0" /* offset 1443 */
+  "\xd0\xb8\xcc\x86\0" /* offset 1448 */
+  "\xd0\xb5\xcc\x80\0" /* offset 1453 */
+  "\xd0\xb5\xcc\x88\0" /* offset 1458 */
+  "\xd0\xb3\xcc\x81\0" /* offset 1463 */
+  "\xd1\x96\xcc\x88\0" /* offset 1468 */
+  "\xd0\xba\xcc\x81\0" /* offset 1473 */
+  "\xd0\xb8\xcc\x80\0" /* offset 1478 */
+  "\xd1\x83\xcc\x86\0" /* offset 1483 */
+  "\xd1\xb4\xcc\x8f\0" /* offset 1488 */
+  "\xd1\xb5\xcc\x8f\0" /* offset 1493 */
+  "\xd0\x96\xcc\x86\0" /* offset 1498 */
+  "\xd0\xb6\xcc\x86\0" /* offset 1503 */
+  "\xd0\x90\xcc\x86\0" /* offset 1508 */
+  "\xd0\xb0\xcc\x86\0" /* offset 1513 */
+  "\xd0\x90\xcc\x88\0" /* offset 1518 */
+  "\xd0\xb0\xcc\x88\0" /* offset 1523 */
+  "\xd0\x95\xcc\x86\0" /* offset 1528 */
+  "\xd0\xb5\xcc\x86\0" /* offset 1533 */
+  "\xd3\x98\xcc\x88\0" /* offset 1538 */
+  "\xd3\x99\xcc\x88\0" /* offset 1543 */
+  "\xd0\x96\xcc\x88\0" /* offset 1548 */
+  "\xd0\xb6\xcc\x88\0" /* offset 1553 */
+  "\xd0\x97\xcc\x88\0" /* offset 1558 */
+  "\xd0\xb7\xcc\x88\0" /* offset 1563 */
+  "\xd0\x98\xcc\x84\0" /* offset 1568 */
+  "\xd0\xb8\xcc\x84\0" /* offset 1573 */
+  "\xd0\x98\xcc\x88\0" /* offset 1578 */
+  "\xd0\xb8\xcc\x88\0" /* offset 1583 */
+  "\xd0\x9e\xcc\x88\0" /* offset 1588 */
+  "\xd0\xbe\xcc\x88\0" /* offset 1593 */
+  "\xd3\xa8\xcc\x88\0" /* offset 1598 */
+  "\xd3\xa9\xcc\x88\0" /* offset 1603 */
+  "\xd0\xad\xcc\x88\0" /* offset 1608 */
+  "\xd1\x8d\xcc\x88\0" /* offset 1613 */
+  "\xd0\xa3\xcc\x84\0" /* offset 1618 */
+  "\xd1\x83\xcc\x84\0" /* offset 1623 */
+  "\xd0\xa3\xcc\x88\0" /* offset 1628 */
+  "\xd1\x83\xcc\x88\0" /* offset 1633 */
+  "\xd0\xa3\xcc\x8b\0" /* offset 1638 */
+  "\xd1\x83\xcc\x8b\0" /* offset 1643 */
+  "\xd0\xa7\xcc\x88\0" /* offset 1648 */
+  "\xd1\x87\xcc\x88\0" /* offset 1653 */
+  "\xd0\xab\xcc\x88\0" /* offset 1658 */
+  "\xd1\x8b\xcc\x88\0" /* offset 1663 */
+  "\xd5\xa5\xd6\x82\0" /* offset 1668 */
+  "\xd8\xa7\xd9\x93\0" /* offset 1673 */
+  "\xd8\xa7\xd9\x94\0" /* offset 1678 */
+  "\xd9\x88\xd9\x94\0" /* offset 1683 */
+  "\xd8\xa7\xd9\x95\0" /* offset 1688 */
+  "\xd9\x8a\xd9\x94\0" /* offset 1693 */
+  "\xd8\xa7\xd9\xb4\0" /* offset 1698 */
+  "\xd9\x88\xd9\xb4\0" /* offset 1703 */
+  "\xdb\x87\xd9\xb4\0" /* offset 1708 */
+  "\xd9\x8a\xd9\xb4\0" /* offset 1713 */
+  "\xdb\x95\xd9\x94\0" /* offset 1718 */
+  "\xdb\x81\xd9\x94\0" /* offset 1723 */
+  "\xdb\x92\xd9\x94\0" /* offset 1728 */
+  "\xe0\xa4\xa8\xe0\xa4\xbc\0" /* offset 1733 */
+  "\xe0\xa4\xb0\xe0\xa4\xbc\0" /* offset 1740 */
+  "\xe0\xa4\xb3\xe0\xa4\xbc\0" /* offset 1747 */
+  "\xe0\xa4\x95\xe0\xa4\xbc\0" /* offset 1754 */
+  "\xe0\xa4\x96\xe0\xa4\xbc\0" /* offset 1761 */
+  "\xe0\xa4\x97\xe0\xa4\xbc\0" /* offset 1768 */
+  "\xe0\xa4\x9c\xe0\xa4\xbc\0" /* offset 1775 */
+  "\xe0\xa4\xa1\xe0\xa4\xbc\0" /* offset 1782 */
+  "\xe0\xa4\xa2\xe0\xa4\xbc\0" /* offset 1789 */
+  "\xe0\xa4\xab\xe0\xa4\xbc\0" /* offset 1796 */
+  "\xe0\xa4\xaf\xe0\xa4\xbc\0" /* offset 1803 */
+  "\xe0\xa7\x87\xe0\xa6\xbe\0" /* offset 1810 */
+  "\xe0\xa7\x87\xe0\xa7\x97\0" /* offset 1817 */
+  "\xe0\xa6\xa1\xe0\xa6\xbc\0" /* offset 1824 */
+  "\xe0\xa6\xa2\xe0\xa6\xbc\0" /* offset 1831 */
+  "\xe0\xa6\xaf\xe0\xa6\xbc\0" /* offset 1838 */
+  "\xe0\xa8\xb2\xe0\xa8\xbc\0" /* offset 1845 */
+  "\xe0\xa8\xb8\xe0\xa8\xbc\0" /* offset 1852 */
+  "\xe0\xa8\x96\xe0\xa8\xbc\0" /* offset 1859 */
+  "\xe0\xa8\x97\xe0\xa8\xbc\0" /* offset 1866 */
+  "\xe0\xa8\x9c\xe0\xa8\xbc\0" /* offset 1873 */
+  "\xe0\xa8\xab\xe0\xa8\xbc\0" /* offset 1880 */
+  "\xe0\xad\x87\xe0\xad\x96\0" /* offset 1887 */
+  "\xe0\xad\x87\xe0\xac\xbe\0" /* offset 1894 */
+  "\xe0\xad\x87\xe0\xad\x97\0" /* offset 1901 */
+  "\xe0\xac\xa1\xe0\xac\xbc\0" /* offset 1908 */
+  "\xe0\xac\xa2\xe0\xac\xbc\0" /* offset 1915 */
+  "\xe0\xae\x92\xe0\xaf\x97\0" /* offset 1922 */
+  "\xe0\xaf\x86\xe0\xae\xbe\0" /* offset 1929 */
+  "\xe0\xaf\x87\xe0\xae\xbe\0" /* offset 1936 */
+  "\xe0\xaf\x86\xe0\xaf\x97\0" /* offset 1943 */
+  "\xe0\xb1\x86\xe0\xb1\x96\0" /* offset 1950 */
+  "\xe0\xb2\xbf\xe0\xb3\x95\0" /* offset 1957 */
+  "\xe0\xb3\x86\xe0\xb3\x95\0" /* offset 1964 */
+  "\xe0\xb3\x86\xe0\xb3\x96\0" /* offset 1971 */
+  "\xe0\xb3\x86\xe0\xb3\x82\0" /* offset 1978 */
+  "\xe0\xb3\x86\xe0\xb3\x82\xe0\xb3\x95\0" /* offset 1985 */
+  "\xe0\xb5\x86\xe0\xb4\xbe\0" /* offset 1995 */
+  "\xe0\xb5\x87\xe0\xb4\xbe\0" /* offset 2002 */
+  "\xe0\xb5\x86\xe0\xb5\x97\0" /* offset 2009 */
+  "\xe0\xb7\x99\xe0\xb7\x8a\0" /* offset 2016 */
+  "\xe0\xb7\x99\xe0\xb7\x8f\0" /* offset 2023 */
+  "\xe0\xb7\x99\xe0\xb7\x8f\xe0\xb7\x8a\0" /* offset 2030 */
+  "\xe0\xb7\x99\xe0\xb7\x9f\0" /* offset 2040 */
+  "\xe0\xb9\x8d\xe0\xb8\xb2\0" /* offset 2047 */
+  "\xe0\xbb\x8d\xe0\xba\xb2\0" /* offset 2054 */
+  "\xe0\xba\xab\xe0\xba\x99\0" /* offset 2061 */
+  "\xe0\xba\xab\xe0\xba\xa1\0" /* offset 2068 */
+  "\xe0\xbc\x8b\0" /* offset 2075 */
+  "\xe0\xbd\x82\xe0\xbe\xb7\0" /* offset 2079 */
+  "\xe0\xbd\x8c\xe0\xbe\xb7\0" /* offset 2086 */
+  "\xe0\xbd\x91\xe0\xbe\xb7\0" /* offset 2093 */
+  "\xe0\xbd\x96\xe0\xbe\xb7\0" /* offset 2100 */
+  "\xe0\xbd\x9b\xe0\xbe\xb7\0" /* offset 2107 */
+  "\xe0\xbd\x80\xe0\xbe\xb5\0" /* offset 2114 */
+  "\xe0\xbd\xb1\xe0\xbd\xb2\0" /* offset 2121 */
+  "\xe0\xbd\xb1\xe0\xbd\xb4\0" /* offset 2128 */
+  "\xe0\xbe\xb2\xe0\xbe\x80\0" /* offset 2135 */
+  "\xe0\xbe\xb2\xe0\xbd\xb1\xe0\xbe\x80\0" /* offset 2142 */
+  "\xe0\xbe\xb3\xe0\xbe\x80\0" /* offset 2152 */
+  "\xe0\xbe\xb3\xe0\xbd\xb1\xe0\xbe\x80\0" /* offset 2159 */
+  "\xe0\xbd\xb1\xe0\xbe\x80\0" /* offset 2169 */
+  "\xe0\xbe\x92\xe0\xbe\xb7\0" /* offset 2176 */
+  "\xe0\xbe\x9c\xe0\xbe\xb7\0" /* offset 2183 */
+  "\xe0\xbe\xa1\xe0\xbe\xb7\0" /* offset 2190 */
+  "\xe0\xbe\xa6\xe0\xbe\xb7\0" /* offset 2197 */
+  "\xe0\xbe\xab\xe0\xbe\xb7\0" /* offset 2204 */
+  "\xe0\xbe\x90\xe0\xbe\xb5\0" /* offset 2211 */
+  "\xe1\x80\xa5\xe1\x80\xae\0" /* offset 2218 */
+  "\x41\xcc\xa5\0" /* offset 2225 */
+  "\x61\xcc\xa5\0" /* offset 2229 */
+  "\x42\xcc\x87\0" /* offset 2233 */
+  "\x62\xcc\x87\0" /* offset 2237 */
+  "\x42\xcc\xa3\0" /* offset 2241 */
+  "\x62\xcc\xa3\0" /* offset 2245 */
+  "\x42\xcc\xb1\0" /* offset 2249 */
+  "\x62\xcc\xb1\0" /* offset 2253 */
+  "\x43\xcc\xa7\xcc\x81\0" /* offset 2257 */
+  "\x63\xcc\xa7\xcc\x81\0" /* offset 2263 */
+  "\x44\xcc\x87\0" /* offset 2269 */
+  "\x64\xcc\x87\0" /* offset 2273 */
+  "\x44\xcc\xa3\0" /* offset 2277 */
+  "\x64\xcc\xa3\0" /* offset 2281 */
+  "\x44\xcc\xb1\0" /* offset 2285 */
+  "\x64\xcc\xb1\0" /* offset 2289 */
+  "\x44\xcc\xa7\0" /* offset 2293 */
+  "\x64\xcc\xa7\0" /* offset 2297 */
+  "\x44\xcc\xad\0" /* offset 2301 */
+  "\x64\xcc\xad\0" /* offset 2305 */
+  "\x45\xcc\x84\xcc\x80\0" /* offset 2309 */
+  "\x65\xcc\x84\xcc\x80\0" /* offset 2315 */
+  "\x45\xcc\x84\xcc\x81\0" /* offset 2321 */
+  "\x65\xcc\x84\xcc\x81\0" /* offset 2327 */
+  "\x45\xcc\xad\0" /* offset 2333 */
+  "\x65\xcc\xad\0" /* offset 2337 */
+  "\x45\xcc\xb0\0" /* offset 2341 */
+  "\x65\xcc\xb0\0" /* offset 2345 */
+  "\x45\xcc\xa7\xcc\x86\0" /* offset 2349 */
+  "\x65\xcc\xa7\xcc\x86\0" /* offset 2355 */
+  "\x46\xcc\x87\0" /* offset 2361 */
+  "\x66\xcc\x87\0" /* offset 2365 */
+  "\x47\xcc\x84\0" /* offset 2369 */
+  "\x67\xcc\x84\0" /* offset 2373 */
+  "\x48\xcc\x87\0" /* offset 2377 */
+  "\x68\xcc\x87\0" /* offset 2381 */
+  "\x48\xcc\xa3\0" /* offset 2385 */
+  "\x68\xcc\xa3\0" /* offset 2389 */
+  "\x48\xcc\x88\0" /* offset 2393 */
+  "\x68\xcc\x88\0" /* offset 2397 */
+  "\x48\xcc\xa7\0" /* offset 2401 */
+  "\x68\xcc\xa7\0" /* offset 2405 */
+  "\x48\xcc\xae\0" /* offset 2409 */
+  "\x68\xcc\xae\0" /* offset 2413 */
+  "\x49\xcc\xb0\0" /* offset 2417 */
+  "\x69\xcc\xb0\0" /* offset 2421 */
+  "\x49\xcc\x88\xcc\x81\0" /* offset 2425 */
+  "\x69\xcc\x88\xcc\x81\0" /* offset 2431 */
+  "\x4b\xcc\x81\0" /* offset 2437 */
+  "\x6b\xcc\x81\0" /* offset 2441 */
+  "\x4b\xcc\xa3\0" /* offset 2445 */
+  "\x6b\xcc\xa3\0" /* offset 2449 */
+  "\x4b\xcc\xb1\0" /* offset 2453 */
+  "\x6b\xcc\xb1\0" /* offset 2457 */
+  "\x4c\xcc\xa3\0" /* offset 2461 */
+  "\x6c\xcc\xa3\0" /* offset 2465 */
+  "\x4c\xcc\xa3\xcc\x84\0" /* offset 2469 */
+  "\x6c\xcc\xa3\xcc\x84\0" /* offset 2475 */
+  "\x4c\xcc\xb1\0" /* offset 2481 */
+  "\x6c\xcc\xb1\0" /* offset 2485 */
+  "\x4c\xcc\xad\0" /* offset 2489 */
+  "\x6c\xcc\xad\0" /* offset 2493 */
+  "\x4d\xcc\x81\0" /* offset 2497 */
+  "\x6d\xcc\x81\0" /* offset 2501 */
+  "\x4d\xcc\x87\0" /* offset 2505 */
+  "\x6d\xcc\x87\0" /* offset 2509 */
+  "\x4d\xcc\xa3\0" /* offset 2513 */
+  "\x6d\xcc\xa3\0" /* offset 2517 */
+  "\x4e\xcc\x87\0" /* offset 2521 */
+  "\x6e\xcc\x87\0" /* offset 2525 */
+  "\x4e\xcc\xa3\0" /* offset 2529 */
+  "\x6e\xcc\xa3\0" /* offset 2533 */
+  "\x4e\xcc\xb1\0" /* offset 2537 */
+  "\x6e\xcc\xb1\0" /* offset 2541 */
+  "\x4e\xcc\xad\0" /* offset 2545 */
+  "\x6e\xcc\xad\0" /* offset 2549 */
+  "\x4f\xcc\x83\xcc\x81\0" /* offset 2553 */
+  "\x6f\xcc\x83\xcc\x81\0" /* offset 2559 */
+  "\x4f\xcc\x83\xcc\x88\0" /* offset 2565 */
+  "\x6f\xcc\x83\xcc\x88\0" /* offset 2571 */
+  "\x4f\xcc\x84\xcc\x80\0" /* offset 2577 */
+  "\x6f\xcc\x84\xcc\x80\0" /* offset 2583 */
+  "\x4f\xcc\x84\xcc\x81\0" /* offset 2589 */
+  "\x6f\xcc\x84\xcc\x81\0" /* offset 2595 */
+  "\x50\xcc\x81\0" /* offset 2601 */
+  "\x70\xcc\x81\0" /* offset 2605 */
+  "\x50\xcc\x87\0" /* offset 2609 */
+  "\x70\xcc\x87\0" /* offset 2613 */
+  "\x52\xcc\x87\0" /* offset 2617 */
+  "\x72\xcc\x87\0" /* offset 2621 */
+  "\x52\xcc\xa3\0" /* offset 2625 */
+  "\x72\xcc\xa3\0" /* offset 2629 */
+  "\x52\xcc\xa3\xcc\x84\0" /* offset 2633 */
+  "\x72\xcc\xa3\xcc\x84\0" /* offset 2639 */
+  "\x52\xcc\xb1\0" /* offset 2645 */
+  "\x72\xcc\xb1\0" /* offset 2649 */
+  "\x53\xcc\x87\0" /* offset 2653 */
+  "\x73\xcc\x87\0" /* offset 2657 */
+  "\x53\xcc\xa3\0" /* offset 2661 */
+  "\x73\xcc\xa3\0" /* offset 2665 */
+  "\x53\xcc\x81\xcc\x87\0" /* offset 2669 */
+  "\x73\xcc\x81\xcc\x87\0" /* offset 2675 */
+  "\x53\xcc\x8c\xcc\x87\0" /* offset 2681 */
+  "\x73\xcc\x8c\xcc\x87\0" /* offset 2687 */
+  "\x53\xcc\xa3\xcc\x87\0" /* offset 2693 */
+  "\x73\xcc\xa3\xcc\x87\0" /* offset 2699 */
+  "\x54\xcc\x87\0" /* offset 2705 */
+  "\x74\xcc\x87\0" /* offset 2709 */
+  "\x54\xcc\xa3\0" /* offset 2713 */
+  "\x74\xcc\xa3\0" /* offset 2717 */
+  "\x54\xcc\xb1\0" /* offset 2721 */
+  "\x74\xcc\xb1\0" /* offset 2725 */
+  "\x54\xcc\xad\0" /* offset 2729 */
+  "\x74\xcc\xad\0" /* offset 2733 */
+  "\x55\xcc\xa4\0" /* offset 2737 */
+  "\x75\xcc\xa4\0" /* offset 2741 */
+  "\x55\xcc\xb0\0" /* offset 2745 */
+  "\x75\xcc\xb0\0" /* offset 2749 */
+  "\x55\xcc\xad\0" /* offset 2753 */
+  "\x75\xcc\xad\0" /* offset 2757 */
+  "\x55\xcc\x83\xcc\x81\0" /* offset 2761 */
+  "\x75\xcc\x83\xcc\x81\0" /* offset 2767 */
+  "\x55\xcc\x84\xcc\x88\0" /* offset 2773 */
+  "\x75\xcc\x84\xcc\x88\0" /* offset 2779 */
+  "\x56\xcc\x83\0" /* offset 2785 */
+  "\x76\xcc\x83\0" /* offset 2789 */
+  "\x56\xcc\xa3\0" /* offset 2793 */
+  "\x76\xcc\xa3\0" /* offset 2797 */
+  "\x57\xcc\x80\0" /* offset 2801 */
+  "\x77\xcc\x80\0" /* offset 2805 */
+  "\x57\xcc\x81\0" /* offset 2809 */
+  "\x77\xcc\x81\0" /* offset 2813 */
+  "\x57\xcc\x88\0" /* offset 2817 */
+  "\x77\xcc\x88\0" /* offset 2821 */
+  "\x57\xcc\x87\0" /* offset 2825 */
+  "\x77\xcc\x87\0" /* offset 2829 */
+  "\x57\xcc\xa3\0" /* offset 2833 */
+  "\x77\xcc\xa3\0" /* offset 2837 */
+  "\x58\xcc\x87\0" /* offset 2841 */
+  "\x78\xcc\x87\0" /* offset 2845 */
+  "\x58\xcc\x88\0" /* offset 2849 */
+  "\x78\xcc\x88\0" /* offset 2853 */
+  "\x59\xcc\x87\0" /* offset 2857 */
+  "\x79\xcc\x87\0" /* offset 2861 */
+  "\x5a\xcc\x82\0" /* offset 2865 */
+  "\x7a\xcc\x82\0" /* offset 2869 */
+  "\x5a\xcc\xa3\0" /* offset 2873 */
+  "\x7a\xcc\xa3\0" /* offset 2877 */
+  "\x5a\xcc\xb1\0" /* offset 2881 */
+  "\x7a\xcc\xb1\0" /* offset 2885 */
+  "\x68\xcc\xb1\0" /* offset 2889 */
+  "\x74\xcc\x88\0" /* offset 2893 */
+  "\x77\xcc\x8a\0" /* offset 2897 */
+  "\x79\xcc\x8a\0" /* offset 2901 */
+  "\x61\xca\xbe\0" /* offset 2905 */
+  "\xc5\xbf\xcc\x87\0" /* offset 2909 */
+  "\x41\xcc\xa3\0" /* offset 2914 */
+  "\x61\xcc\xa3\0" /* offset 2918 */
+  "\x41\xcc\x89\0" /* offset 2922 */
+  "\x61\xcc\x89\0" /* offset 2926 */
+  "\x41\xcc\x82\xcc\x81\0" /* offset 2930 */
+  "\x61\xcc\x82\xcc\x81\0" /* offset 2936 */
+  "\x41\xcc\x82\xcc\x80\0" /* offset 2942 */
+  "\x61\xcc\x82\xcc\x80\0" /* offset 2948 */
+  "\x41\xcc\x82\xcc\x89\0" /* offset 2954 */
+  "\x61\xcc\x82\xcc\x89\0" /* offset 2960 */
+  "\x41\xcc\x82\xcc\x83\0" /* offset 2966 */
+  "\x61\xcc\x82\xcc\x83\0" /* offset 2972 */
+  "\x41\xcc\xa3\xcc\x82\0" /* offset 2978 */
+  "\x61\xcc\xa3\xcc\x82\0" /* offset 2984 */
+  "\x41\xcc\x86\xcc\x81\0" /* offset 2990 */
+  "\x61\xcc\x86\xcc\x81\0" /* offset 2996 */
+  "\x41\xcc\x86\xcc\x80\0" /* offset 3002 */
+  "\x61\xcc\x86\xcc\x80\0" /* offset 3008 */
+  "\x41\xcc\x86\xcc\x89\0" /* offset 3014 */
+  "\x61\xcc\x86\xcc\x89\0" /* offset 3020 */
+  "\x41\xcc\x86\xcc\x83\0" /* offset 3026 */
+  "\x61\xcc\x86\xcc\x83\0" /* offset 3032 */
+  "\x41\xcc\xa3\xcc\x86\0" /* offset 3038 */
+  "\x61\xcc\xa3\xcc\x86\0" /* offset 3044 */
+  "\x45\xcc\xa3\0" /* offset 3050 */
+  "\x65\xcc\xa3\0" /* offset 3054 */
+  "\x45\xcc\x89\0" /* offset 3058 */
+  "\x65\xcc\x89\0" /* offset 3062 */
+  "\x45\xcc\x83\0" /* offset 3066 */
+  "\x65\xcc\x83\0" /* offset 3070 */
+  "\x45\xcc\x82\xcc\x81\0" /* offset 3074 */
+  "\x65\xcc\x82\xcc\x81\0" /* offset 3080 */
+  "\x45\xcc\x82\xcc\x80\0" /* offset 3086 */
+  "\x65\xcc\x82\xcc\x80\0" /* offset 3092 */
+  "\x45\xcc\x82\xcc\x89\0" /* offset 3098 */
+  "\x65\xcc\x82\xcc\x89\0" /* offset 3104 */
+  "\x45\xcc\x82\xcc\x83\0" /* offset 3110 */
+  "\x65\xcc\x82\xcc\x83\0" /* offset 3116 */
+  "\x45\xcc\xa3\xcc\x82\0" /* offset 3122 */
+  "\x65\xcc\xa3\xcc\x82\0" /* offset 3128 */
+  "\x49\xcc\x89\0" /* offset 3134 */
+  "\x69\xcc\x89\0" /* offset 3138 */
+  "\x49\xcc\xa3\0" /* offset 3142 */
+  "\x69\xcc\xa3\0" /* offset 3146 */
+  "\x4f\xcc\xa3\0" /* offset 3150 */
+  "\x6f\xcc\xa3\0" /* offset 3154 */
+  "\x4f\xcc\x89\0" /* offset 3158 */
+  "\x6f\xcc\x89\0" /* offset 3162 */
+  "\x4f\xcc\x82\xcc\x81\0" /* offset 3166 */
+  "\x6f\xcc\x82\xcc\x81\0" /* offset 3172 */
+  "\x4f\xcc\x82\xcc\x80\0" /* offset 3178 */
+  "\x6f\xcc\x82\xcc\x80\0" /* offset 3184 */
+  "\x4f\xcc\x82\xcc\x89\0" /* offset 3190 */
+  "\x6f\xcc\x82\xcc\x89\0" /* offset 3196 */
+  "\x4f\xcc\x82\xcc\x83\0" /* offset 3202 */
+  "\x6f\xcc\x82\xcc\x83\0" /* offset 3208 */
+  "\x4f\xcc\xa3\xcc\x82\0" /* offset 3214 */
+  "\x6f\xcc\xa3\xcc\x82\0" /* offset 3220 */
+  "\x4f\xcc\x9b\xcc\x81\0" /* offset 3226 */
+  "\x6f\xcc\x9b\xcc\x81\0" /* offset 3232 */
+  "\x4f\xcc\x9b\xcc\x80\0" /* offset 3238 */
+  "\x6f\xcc\x9b\xcc\x80\0" /* offset 3244 */
+  "\x4f\xcc\x9b\xcc\x89\0" /* offset 3250 */
+  "\x6f\xcc\x9b\xcc\x89\0" /* offset 3256 */
+  "\x4f\xcc\x9b\xcc\x83\0" /* offset 3262 */
+  "\x6f\xcc\x9b\xcc\x83\0" /* offset 3268 */
+  "\x4f\xcc\x9b\xcc\xa3\0" /* offset 3274 */
+  "\x6f\xcc\x9b\xcc\xa3\0" /* offset 3280 */
+  "\x55\xcc\xa3\0" /* offset 3286 */
+  "\x75\xcc\xa3\0" /* offset 3290 */
+  "\x55\xcc\x89\0" /* offset 3294 */
+  "\x75\xcc\x89\0" /* offset 3298 */
+  "\x55\xcc\x9b\xcc\x81\0" /* offset 3302 */
+  "\x75\xcc\x9b\xcc\x81\0" /* offset 3308 */
+  "\x55\xcc\x9b\xcc\x80\0" /* offset 3314 */
+  "\x75\xcc\x9b\xcc\x80\0" /* offset 3320 */
+  "\x55\xcc\x9b\xcc\x89\0" /* offset 3326 */
+  "\x75\xcc\x9b\xcc\x89\0" /* offset 3332 */
+  "\x55\xcc\x9b\xcc\x83\0" /* offset 3338 */
+  "\x75\xcc\x9b\xcc\x83\0" /* offset 3344 */
+  "\x55\xcc\x9b\xcc\xa3\0" /* offset 3350 */
+  "\x75\xcc\x9b\xcc\xa3\0" /* offset 3356 */
+  "\x59\xcc\x80\0" /* offset 3362 */
+  "\x79\xcc\x80\0" /* offset 3366 */
+  "\x59\xcc\xa3\0" /* offset 3370 */
+  "\x79\xcc\xa3\0" /* offset 3374 */
+  "\x59\xcc\x89\0" /* offset 3378 */
+  "\x79\xcc\x89\0" /* offset 3382 */
+  "\x59\xcc\x83\0" /* offset 3386 */
+  "\x79\xcc\x83\0" /* offset 3390 */
+  "\xce\xb1\xcc\x93\0" /* offset 3394 */
+  "\xce\xb1\xcc\x94\0" /* offset 3399 */
+  "\xce\xb1\xcc\x93\xcc\x80\0" /* offset 3404 */
+  "\xce\xb1\xcc\x94\xcc\x80\0" /* offset 3411 */
+  "\xce\xb1\xcc\x93\xcc\x81\0" /* offset 3418 */
+  "\xce\xb1\xcc\x94\xcc\x81\0" /* offset 3425 */
+  "\xce\xb1\xcc\x93\xcd\x82\0" /* offset 3432 */
+  "\xce\xb1\xcc\x94\xcd\x82\0" /* offset 3439 */
+  "\xce\x91\xcc\x93\0" /* offset 3446 */
+  "\xce\x91\xcc\x94\0" /* offset 3451 */
+  "\xce\x91\xcc\x93\xcc\x80\0" /* offset 3456 */
+  "\xce\x91\xcc\x94\xcc\x80\0" /* offset 3463 */
+  "\xce\x91\xcc\x93\xcc\x81\0" /* offset 3470 */
+  "\xce\x91\xcc\x94\xcc\x81\0" /* offset 3477 */
+  "\xce\x91\xcc\x93\xcd\x82\0" /* offset 3484 */
+  "\xce\x91\xcc\x94\xcd\x82\0" /* offset 3491 */
+  "\xce\xb5\xcc\x93\0" /* offset 3498 */
+  "\xce\xb5\xcc\x94\0" /* offset 3503 */
+  "\xce\xb5\xcc\x93\xcc\x80\0" /* offset 3508 */
+  "\xce\xb5\xcc\x94\xcc\x80\0" /* offset 3515 */
+  "\xce\xb5\xcc\x93\xcc\x81\0" /* offset 3522 */
+  "\xce\xb5\xcc\x94\xcc\x81\0" /* offset 3529 */
+  "\xce\x95\xcc\x93\0" /* offset 3536 */
+  "\xce\x95\xcc\x94\0" /* offset 3541 */
+  "\xce\x95\xcc\x93\xcc\x80\0" /* offset 3546 */
+  "\xce\x95\xcc\x94\xcc\x80\0" /* offset 3553 */
+  "\xce\x95\xcc\x93\xcc\x81\0" /* offset 3560 */
+  "\xce\x95\xcc\x94\xcc\x81\0" /* offset 3567 */
+  "\xce\xb7\xcc\x93\0" /* offset 3574 */
+  "\xce\xb7\xcc\x94\0" /* offset 3579 */
+  "\xce\xb7\xcc\x93\xcc\x80\0" /* offset 3584 */
+  "\xce\xb7\xcc\x94\xcc\x80\0" /* offset 3591 */
+  "\xce\xb7\xcc\x93\xcc\x81\0" /* offset 3598 */
+  "\xce\xb7\xcc\x94\xcc\x81\0" /* offset 3605 */
+  "\xce\xb7\xcc\x93\xcd\x82\0" /* offset 3612 */
+  "\xce\xb7\xcc\x94\xcd\x82\0" /* offset 3619 */
+  "\xce\x97\xcc\x93\0" /* offset 3626 */
+  "\xce\x97\xcc\x94\0" /* offset 3631 */
+  "\xce\x97\xcc\x93\xcc\x80\0" /* offset 3636 */
+  "\xce\x97\xcc\x94\xcc\x80\0" /* offset 3643 */
+  "\xce\x97\xcc\x93\xcc\x81\0" /* offset 3650 */
+  "\xce\x97\xcc\x94\xcc\x81\0" /* offset 3657 */
+  "\xce\x97\xcc\x93\xcd\x82\0" /* offset 3664 */
+  "\xce\x97\xcc\x94\xcd\x82\0" /* offset 3671 */
+  "\xce\xb9\xcc\x93\0" /* offset 3678 */
+  "\xce\xb9\xcc\x94\0" /* offset 3683 */
+  "\xce\xb9\xcc\x93\xcc\x80\0" /* offset 3688 */
+  "\xce\xb9\xcc\x94\xcc\x80\0" /* offset 3695 */
+  "\xce\xb9\xcc\x93\xcc\x81\0" /* offset 3702 */
+  "\xce\xb9\xcc\x94\xcc\x81\0" /* offset 3709 */
+  "\xce\xb9\xcc\x93\xcd\x82\0" /* offset 3716 */
+  "\xce\xb9\xcc\x94\xcd\x82\0" /* offset 3723 */
+  "\xce\x99\xcc\x93\0" /* offset 3730 */
+  "\xce\x99\xcc\x94\0" /* offset 3735 */
+  "\xce\x99\xcc\x93\xcc\x80\0" /* offset 3740 */
+  "\xce\x99\xcc\x94\xcc\x80\0" /* offset 3747 */
+  "\xce\x99\xcc\x93\xcc\x81\0" /* offset 3754 */
+  "\xce\x99\xcc\x94\xcc\x81\0" /* offset 3761 */
+  "\xce\x99\xcc\x93\xcd\x82\0" /* offset 3768 */
+  "\xce\x99\xcc\x94\xcd\x82\0" /* offset 3775 */
+  "\xce\xbf\xcc\x93\0" /* offset 3782 */
+  "\xce\xbf\xcc\x94\0" /* offset 3787 */
+  "\xce\xbf\xcc\x93\xcc\x80\0" /* offset 3792 */
+  "\xce\xbf\xcc\x94\xcc\x80\0" /* offset 3799 */
+  "\xce\xbf\xcc\x93\xcc\x81\0" /* offset 3806 */
+  "\xce\xbf\xcc\x94\xcc\x81\0" /* offset 3813 */
+  "\xce\x9f\xcc\x93\0" /* offset 3820 */
+  "\xce\x9f\xcc\x94\0" /* offset 3825 */
+  "\xce\x9f\xcc\x93\xcc\x80\0" /* offset 3830 */
+  "\xce\x9f\xcc\x94\xcc\x80\0" /* offset 3837 */
+  "\xce\x9f\xcc\x93\xcc\x81\0" /* offset 3844 */
+  "\xce\x9f\xcc\x94\xcc\x81\0" /* offset 3851 */
+  "\xcf\x85\xcc\x93\0" /* offset 3858 */
+  "\xcf\x85\xcc\x94\0" /* offset 3863 */
+  "\xcf\x85\xcc\x93\xcc\x80\0" /* offset 3868 */
+  "\xcf\x85\xcc\x94\xcc\x80\0" /* offset 3875 */
+  "\xcf\x85\xcc\x93\xcc\x81\0" /* offset 3882 */
+  "\xcf\x85\xcc\x94\xcc\x81\0" /* offset 3889 */
+  "\xcf\x85\xcc\x93\xcd\x82\0" /* offset 3896 */
+  "\xcf\x85\xcc\x94\xcd\x82\0" /* offset 3903 */
+  "\xce\xa5\xcc\x94\0" /* offset 3910 */
+  "\xce\xa5\xcc\x94\xcc\x80\0" /* offset 3915 */
+  "\xce\xa5\xcc\x94\xcc\x81\0" /* offset 3922 */
+  "\xce\xa5\xcc\x94\xcd\x82\0" /* offset 3929 */
+  "\xcf\x89\xcc\x93\0" /* offset 3936 */
+  "\xcf\x89\xcc\x94\0" /* offset 3941 */
+  "\xcf\x89\xcc\x93\xcc\x80\0" /* offset 3946 */
+  "\xcf\x89\xcc\x94\xcc\x80\0" /* offset 3953 */
+  "\xcf\x89\xcc\x93\xcc\x81\0" /* offset 3960 */
+  "\xcf\x89\xcc\x94\xcc\x81\0" /* offset 3967 */
+  "\xcf\x89\xcc\x93\xcd\x82\0" /* offset 3974 */
+  "\xcf\x89\xcc\x94\xcd\x82\0" /* offset 3981 */
+  "\xce\xa9\xcc\x93\0" /* offset 3988 */
+  "\xce\xa9\xcc\x94\0" /* offset 3993 */
+  "\xce\xa9\xcc\x93\xcc\x80\0" /* offset 3998 */
+  "\xce\xa9\xcc\x94\xcc\x80\0" /* offset 4005 */
+  "\xce\xa9\xcc\x93\xcc\x81\0" /* offset 4012 */
+  "\xce\xa9\xcc\x94\xcc\x81\0" /* offset 4019 */
+  "\xce\xa9\xcc\x93\xcd\x82\0" /* offset 4026 */
+  "\xce\xa9\xcc\x94\xcd\x82\0" /* offset 4033 */
+  "\xce\xb1\xcc\x80\0" /* offset 4040 */
+  "\xce\xb5\xcc\x80\0" /* offset 4045 */
+  "\xce\xb7\xcc\x80\0" /* offset 4050 */
+  "\xce\xb9\xcc\x80\0" /* offset 4055 */
+  "\xce\xbf\xcc\x80\0" /* offset 4060 */
+  "\xcf\x85\xcc\x80\0" /* offset 4065 */
+  "\xcf\x89\xcc\x80\0" /* offset 4070 */
+  "\xce\xb1\xcc\x93\xcd\x85\0" /* offset 4075 */
+  "\xce\xb1\xcc\x94\xcd\x85\0" /* offset 4082 */
+  "\xce\xb1\xcc\x93\xcc\x80\xcd\x85\0" /* offset 4089 */
+  "\xce\xb1\xcc\x94\xcc\x80\xcd\x85\0" /* offset 4098 */
+  "\xce\xb1\xcc\x93\xcc\x81\xcd\x85\0" /* offset 4107 */
+  "\xce\xb1\xcc\x94\xcc\x81\xcd\x85\0" /* offset 4116 */
+  "\xce\xb1\xcc\x93\xcd\x82\xcd\x85\0" /* offset 4125 */
+  "\xce\xb1\xcc\x94\xcd\x82\xcd\x85\0" /* offset 4134 */
+  "\xce\x91\xcc\x93\xcd\x85\0" /* offset 4143 */
+  "\xce\x91\xcc\x94\xcd\x85\0" /* offset 4150 */
+  "\xce\x91\xcc\x93\xcc\x80\xcd\x85\0" /* offset 4157 */
+  "\xce\x91\xcc\x94\xcc\x80\xcd\x85\0" /* offset 4166 */
+  "\xce\x91\xcc\x93\xcc\x81\xcd\x85\0" /* offset 4175 */
+  "\xce\x91\xcc\x94\xcc\x81\xcd\x85\0" /* offset 4184 */
+  "\xce\x91\xcc\x93\xcd\x82\xcd\x85\0" /* offset 4193 */
+  "\xce\x91\xcc\x94\xcd\x82\xcd\x85\0" /* offset 4202 */
+  "\xce\xb7\xcc\x93\xcd\x85\0" /* offset 4211 */
+  "\xce\xb7\xcc\x94\xcd\x85\0" /* offset 4218 */
+  "\xce\xb7\xcc\x93\xcc\x80\xcd\x85\0" /* offset 4225 */
+  "\xce\xb7\xcc\x94\xcc\x80\xcd\x85\0" /* offset 4234 */
+  "\xce\xb7\xcc\x93\xcc\x81\xcd\x85\0" /* offset 4243 */
+  "\xce\xb7\xcc\x94\xcc\x81\xcd\x85\0" /* offset 4252 */
+  "\xce\xb7\xcc\x93\xcd\x82\xcd\x85\0" /* offset 4261 */
+  "\xce\xb7\xcc\x94\xcd\x82\xcd\x85\0" /* offset 4270 */
+  "\xce\x97\xcc\x93\xcd\x85\0" /* offset 4279 */
+  "\xce\x97\xcc\x94\xcd\x85\0" /* offset 4286 */
+  "\xce\x97\xcc\x93\xcc\x80\xcd\x85\0" /* offset 4293 */
+  "\xce\x97\xcc\x94\xcc\x80\xcd\x85\0" /* offset 4302 */
+  "\xce\x97\xcc\x93\xcc\x81\xcd\x85\0" /* offset 4311 */
+  "\xce\x97\xcc\x94\xcc\x81\xcd\x85\0" /* offset 4320 */
+  "\xce\x97\xcc\x93\xcd\x82\xcd\x85\0" /* offset 4329 */
+  "\xce\x97\xcc\x94\xcd\x82\xcd\x85\0" /* offset 4338 */
+  "\xcf\x89\xcc\x93\xcd\x85\0" /* offset 4347 */
+  "\xcf\x89\xcc\x94\xcd\x85\0" /* offset 4354 */
+  "\xcf\x89\xcc\x93\xcc\x80\xcd\x85\0" /* offset 4361 */
+  "\xcf\x89\xcc\x94\xcc\x80\xcd\x85\0" /* offset 4370 */
+  "\xcf\x89\xcc\x93\xcc\x81\xcd\x85\0" /* offset 4379 */
+  "\xcf\x89\xcc\x94\xcc\x81\xcd\x85\0" /* offset 4388 */
+  "\xcf\x89\xcc\x93\xcd\x82\xcd\x85\0" /* offset 4397 */
+  "\xcf\x89\xcc\x94\xcd\x82\xcd\x85\0" /* offset 4406 */
+  "\xce\xa9\xcc\x93\xcd\x85\0" /* offset 4415 */
+  "\xce\xa9\xcc\x94\xcd\x85\0" /* offset 4422 */
+  "\xce\xa9\xcc\x93\xcc\x80\xcd\x85\0" /* offset 4429 */
+  "\xce\xa9\xcc\x94\xcc\x80\xcd\x85\0" /* offset 4438 */
+  "\xce\xa9\xcc\x93\xcc\x81\xcd\x85\0" /* offset 4447 */
+  "\xce\xa9\xcc\x94\xcc\x81\xcd\x85\0" /* offset 4456 */
+  "\xce\xa9\xcc\x93\xcd\x82\xcd\x85\0" /* offset 4465 */
+  "\xce\xa9\xcc\x94\xcd\x82\xcd\x85\0" /* offset 4474 */
+  "\xce\xb1\xcc\x86\0" /* offset 4483 */
+  "\xce\xb1\xcc\x84\0" /* offset 4488 */
+  "\xce\xb1\xcc\x80\xcd\x85\0" /* offset 4493 */
+  "\xce\xb1\xcd\x85\0" /* offset 4500 */
+  "\xce\xb1\xcc\x81\xcd\x85\0" /* offset 4505 */
+  "\xce\xb1\xcd\x82\0" /* offset 4512 */
+  "\xce\xb1\xcd\x82\xcd\x85\0" /* offset 4517 */
+  "\xce\x91\xcc\x86\0" /* offset 4524 */
+  "\xce\x91\xcc\x84\0" /* offset 4529 */
+  "\xce\x91\xcc\x80\0" /* offset 4534 */
+  "\xce\x91\xcd\x85\0" /* offset 4539 */
+  "\x20\xcc\x93\0" /* offset 4544 */
+  "\xce\xb9\0" /* offset 4548 */
+  "\x20\xcd\x82\0" /* offset 4551 */
+  "\xc2\xa8\xcd\x82\0" /* offset 4555 */
+  "\x20\xcc\x88\xcd\x82\0" /* offset 4560 */
+  "\xce\xb7\xcc\x80\xcd\x85\0" /* offset 4566 */
+  "\xce\xb7\xcd\x85\0" /* offset 4573 */
+  "\xce\xb7\xcc\x81\xcd\x85\0" /* offset 4578 */
+  "\xce\xb7\xcd\x82\0" /* offset 4585 */
+  "\xce\xb7\xcd\x82\xcd\x85\0" /* offset 4590 */
+  "\xce\x95\xcc\x80\0" /* offset 4597 */
+  "\xce\x97\xcc\x80\0" /* offset 4602 */
+  "\xce\x97\xcd\x85\0" /* offset 4607 */
+  "\xe1\xbe\xbf\xcc\x80\0" /* offset 4612 */
+  "\x20\xcc\x93\xcc\x80\0" /* offset 4618 */
+  "\xe1\xbe\xbf\xcc\x81\0" /* offset 4624 */
+  "\x20\xcc\x93\xcc\x81\0" /* offset 4630 */
+  "\xe1\xbe\xbf\xcd\x82\0" /* offset 4636 */
+  "\x20\xcc\x93\xcd\x82\0" /* offset 4642 */
+  "\xce\xb9\xcc\x86\0" /* offset 4648 */
+  "\xce\xb9\xcc\x84\0" /* offset 4653 */
+  "\xce\xb9\xcc\x88\xcc\x80\0" /* offset 4658 */
+  "\xce\xb9\xcd\x82\0" /* offset 4665 */
+  "\xce\xb9\xcc\x88\xcd\x82\0" /* offset 4670 */
+  "\xce\x99\xcc\x86\0" /* offset 4677 */
+  "\xce\x99\xcc\x84\0" /* offset 4682 */
+  "\xce\x99\xcc\x80\0" /* offset 4687 */
+  "\xe1\xbf\xbe\xcc\x80\0" /* offset 4692 */
+  "\x20\xcc\x94\xcc\x80\0" /* offset 4698 */
+  "\xe1\xbf\xbe\xcc\x81\0" /* offset 4704 */
+  "\x20\xcc\x94\xcc\x81\0" /* offset 4710 */
+  "\xe1\xbf\xbe\xcd\x82\0" /* offset 4716 */
+  "\x20\xcc\x94\xcd\x82\0" /* offset 4722 */
+  "\xcf\x85\xcc\x86\0" /* offset 4728 */
+  "\xcf\x85\xcc\x84\0" /* offset 4733 */
+  "\xcf\x85\xcc\x88\xcc\x80\0" /* offset 4738 */
+  "\xcf\x81\xcc\x93\0" /* offset 4745 */
+  "\xcf\x81\xcc\x94\0" /* offset 4750 */
+  "\xcf\x85\xcd\x82\0" /* offset 4755 */
+  "\xcf\x85\xcc\x88\xcd\x82\0" /* offset 4760 */
+  "\xce\xa5\xcc\x86\0" /* offset 4767 */
+  "\xce\xa5\xcc\x84\0" /* offset 4772 */
+  "\xce\xa5\xcc\x80\0" /* offset 4777 */
+  "\xce\xa1\xcc\x94\0" /* offset 4782 */
+  "\xc2\xa8\xcc\x80\0" /* offset 4787 */
+  "\x20\xcc\x88\xcc\x80\0" /* offset 4792 */
+  "\x60\0" /* offset 4798 */
+  "\xcf\x89\xcc\x80\xcd\x85\0" /* offset 4800 */
+  "\xcf\x89\xcd\x85\0" /* offset 4807 */
+  "\xcf\x89\xcc\x81\xcd\x85\0" /* offset 4812 */
+  "\xcf\x89\xcd\x82\0" /* offset 4819 */
+  "\xcf\x89\xcd\x82\xcd\x85\0" /* offset 4824 */
+  "\xce\x9f\xcc\x80\0" /* offset 4831 */
+  "\xce\xa9\xcc\x80\0" /* offset 4836 */
+  "\xce\xa9\xcd\x85\0" /* offset 4841 */
+  "\xc2\xb4\0" /* offset 4846 */
+  "\x20\xcc\x94\0" /* offset 4849 */
+  "\xe2\x80\x82\0" /* offset 4853 */
+  "\xe2\x80\x83\0" /* offset 4857 */
+  "\xe2\x80\x90\0" /* offset 4861 */
+  "\x20\xcc\xb3\0" /* offset 4865 */
+  "\x2e\0" /* offset 4869 */
+  "\x2e\x2e\0" /* offset 4871 */
+  "\x2e\x2e\x2e\0" /* offset 4874 */
+  "\xe2\x80\xb2\xe2\x80\xb2\0" /* offset 4878 */
+  "\xe2\x80\xb2\xe2\x80\xb2\xe2\x80\xb2\0" /* offset 4885 */
+  "\xe2\x80\xb5\xe2\x80\xb5\0" /* offset 4895 */
+  "\xe2\x80\xb5\xe2\x80\xb5\xe2\x80\xb5\0" /* offset 4902 */
+  "\x21\x21\0" /* offset 4912 */
+  "\x20\xcc\x85\0" /* offset 4915 */
+  "\x3f\x3f\0" /* offset 4919 */
+  "\x3f\x21\0" /* offset 4922 */
+  "\x21\x3f\0" /* offset 4925 */
+  "\xe2\x80\xb2\xe2\x80\xb2\xe2\x80\xb2\xe2\x80\xb2\0" /* offset 4928 */
+  "\x30\0" /* offset 4941 */
+  "\x69\0" /* offset 4943 */
+  "\x34\0" /* offset 4945 */
+  "\x35\0" /* offset 4947 */
+  "\x36\0" /* offset 4949 */
+  "\x37\0" /* offset 4951 */
+  "\x38\0" /* offset 4953 */
+  "\x39\0" /* offset 4955 */
+  "\x2b\0" /* offset 4957 */
+  "\xe2\x88\x92\0" /* offset 4959 */
+  "\x3d\0" /* offset 4963 */
+  "\x28\0" /* offset 4965 */
+  "\x29\0" /* offset 4967 */
+  "\x6e\0" /* offset 4969 */
+  "\x52\x73\0" /* offset 4971 */
+  "\x61\x2f\x63\0" /* offset 4974 */
+  "\x61\x2f\x73\0" /* offset 4978 */
+  "\x43\0" /* offset 4982 */
+  "\xc2\xb0\x43\0" /* offset 4984 */
+  "\x63\x2f\x6f\0" /* offset 4988 */
+  "\x63\x2f\x75\0" /* offset 4992 */
+  "\xc6\x90\0" /* offset 4996 */
+  "\xc2\xb0\x46\0" /* offset 4999 */
+  "\x67\0" /* offset 5003 */
+  "\x48\0" /* offset 5005 */
+  "\xc4\xa7\0" /* offset 5007 */
+  "\x49\0" /* offset 5010 */
+  "\x4c\0" /* offset 5012 */
+  "\x4e\0" /* offset 5014 */
+  "\x4e\x6f\0" /* offset 5016 */
+  "\x50\0" /* offset 5019 */
+  "\x51\0" /* offset 5021 */
+  "\x52\0" /* offset 5023 */
+  "\x53\x4d\0" /* offset 5025 */
+  "\x54\x45\x4c\0" /* offset 5028 */
+  "\x54\x4d\0" /* offset 5032 */
+  "\x5a\0" /* offset 5035 */
+  "\xce\xa9\0" /* offset 5037 */
+  "\x4b\0" /* offset 5040 */
+  "\x42\0" /* offset 5042 */
+  "\x65\0" /* offset 5044 */
+  "\x45\0" /* offset 5046 */
+  "\x46\0" /* offset 5048 */
+  "\x4d\0" /* offset 5050 */
+  "\xd7\x90\0" /* offset 5052 */
+  "\xd7\x91\0" /* offset 5055 */
+  "\xd7\x92\0" /* offset 5058 */
+  "\xd7\x93\0" /* offset 5061 */
+  "\xce\xb3\0" /* offset 5064 */
+  "\xce\x93\0" /* offset 5067 */
+  "\xce\xa0\0" /* offset 5070 */
+  "\xe2\x88\x91\0" /* offset 5073 */
+  "\x44\0" /* offset 5077 */
+  "\x64\0" /* offset 5079 */
+  "\x31\xe2\x81\x84\x33\0" /* offset 5081 */
+  "\x32\xe2\x81\x84\x33\0" /* offset 5087 */
+  "\x31\xe2\x81\x84\x35\0" /* offset 5093 */
+  "\x32\xe2\x81\x84\x35\0" /* offset 5099 */
+  "\x33\xe2\x81\x84\x35\0" /* offset 5105 */
+  "\x34\xe2\x81\x84\x35\0" /* offset 5111 */
+  "\x31\xe2\x81\x84\x36\0" /* offset 5117 */
+  "\x35\xe2\x81\x84\x36\0" /* offset 5123 */
+  "\x31\xe2\x81\x84\x38\0" /* offset 5129 */
+  "\x33\xe2\x81\x84\x38\0" /* offset 5135 */
+  "\x35\xe2\x81\x84\x38\0" /* offset 5141 */
+  "\x37\xe2\x81\x84\x38\0" /* offset 5147 */
+  "\x31\xe2\x81\x84\0" /* offset 5153 */
+  "\x49\x49\0" /* offset 5158 */
+  "\x49\x49\x49\0" /* offset 5161 */
+  "\x49\x56\0" /* offset 5165 */
+  "\x56\0" /* offset 5168 */
+  "\x56\x49\0" /* offset 5170 */
+  "\x56\x49\x49\0" /* offset 5173 */
+  "\x56\x49\x49\x49\0" /* offset 5177 */
+  "\x49\x58\0" /* offset 5182 */
+  "\x58\0" /* offset 5185 */
+  "\x58\x49\0" /* offset 5187 */
+  "\x58\x49\x49\0" /* offset 5190 */
+  "\x69\x69\0" /* offset 5194 */
+  "\x69\x69\x69\0" /* offset 5197 */
+  "\x69\x76\0" /* offset 5201 */
+  "\x76\0" /* offset 5204 */
+  "\x76\x69\0" /* offset 5206 */
+  "\x76\x69\x69\0" /* offset 5209 */
+  "\x76\x69\x69\x69\0" /* offset 5213 */
+  "\x69\x78\0" /* offset 5218 */
+  "\x78\x69\0" /* offset 5221 */
+  "\x78\x69\x69\0" /* offset 5224 */
+  "\x63\0" /* offset 5228 */
+  "\x6d\0" /* offset 5230 */
+  "\xe2\x86\x90\xcc\xb8\0" /* offset 5232 */
+  "\xe2\x86\x92\xcc\xb8\0" /* offset 5238 */
+  "\xe2\x86\x94\xcc\xb8\0" /* offset 5244 */
+  "\xe2\x87\x90\xcc\xb8\0" /* offset 5250 */
+  "\xe2\x87\x94\xcc\xb8\0" /* offset 5256 */
+  "\xe2\x87\x92\xcc\xb8\0" /* offset 5262 */
+  "\xe2\x88\x83\xcc\xb8\0" /* offset 5268 */
+  "\xe2\x88\x88\xcc\xb8\0" /* offset 5274 */
+  "\xe2\x88\x8b\xcc\xb8\0" /* offset 5280 */
+  "\xe2\x88\xa3\xcc\xb8\0" /* offset 5286 */
+  "\xe2\x88\xa5\xcc\xb8\0" /* offset 5292 */
+  "\xe2\x88\xab\xe2\x88\xab\0" /* offset 5298 */
+  "\xe2\x88\xab\xe2\x88\xab\xe2\x88\xab\0" /* offset 5305 */
+  "\xe2\x88\xae\xe2\x88\xae\0" /* offset 5315 */
+  "\xe2\x88\xae\xe2\x88\xae\xe2\x88\xae\0" /* offset 5322 */
+  "\xe2\x88\xbc\xcc\xb8\0" /* offset 5332 */
+  "\xe2\x89\x83\xcc\xb8\0" /* offset 5338 */
+  "\xe2\x89\x85\xcc\xb8\0" /* offset 5344 */
+  "\xe2\x89\x88\xcc\xb8\0" /* offset 5350 */
+  "\x3d\xcc\xb8\0" /* offset 5356 */
+  "\xe2\x89\xa1\xcc\xb8\0" /* offset 5360 */
+  "\xe2\x89\x8d\xcc\xb8\0" /* offset 5366 */
+  "\x3c\xcc\xb8\0" /* offset 5372 */
+  "\x3e\xcc\xb8\0" /* offset 5376 */
+  "\xe2\x89\xa4\xcc\xb8\0" /* offset 5380 */
+  "\xe2\x89\xa5\xcc\xb8\0" /* offset 5386 */
+  "\xe2\x89\xb2\xcc\xb8\0" /* offset 5392 */
+  "\xe2\x89\xb3\xcc\xb8\0" /* offset 5398 */
+  "\xe2\x89\xb6\xcc\xb8\0" /* offset 5404 */
+  "\xe2\x89\xb7\xcc\xb8\0" /* offset 5410 */
+  "\xe2\x89\xba\xcc\xb8\0" /* offset 5416 */
+  "\xe2\x89\xbb\xcc\xb8\0" /* offset 5422 */
+  "\xe2\x8a\x82\xcc\xb8\0" /* offset 5428 */
+  "\xe2\x8a\x83\xcc\xb8\0" /* offset 5434 */
+  "\xe2\x8a\x86\xcc\xb8\0" /* offset 5440 */
+  "\xe2\x8a\x87\xcc\xb8\0" /* offset 5446 */
+  "\xe2\x8a\xa2\xcc\xb8\0" /* offset 5452 */
+  "\xe2\x8a\xa8\xcc\xb8\0" /* offset 5458 */
+  "\xe2\x8a\xa9\xcc\xb8\0" /* offset 5464 */
+  "\xe2\x8a\xab\xcc\xb8\0" /* offset 5470 */
+  "\xe2\x89\xbc\xcc\xb8\0" /* offset 5476 */
+  "\xe2\x89\xbd\xcc\xb8\0" /* offset 5482 */
+  "\xe2\x8a\x91\xcc\xb8\0" /* offset 5488 */
+  "\xe2\x8a\x92\xcc\xb8\0" /* offset 5494 */
+  "\xe2\x8a\xb2\xcc\xb8\0" /* offset 5500 */
+  "\xe2\x8a\xb3\xcc\xb8\0" /* offset 5506 */
+  "\xe2\x8a\xb4\xcc\xb8\0" /* offset 5512 */
+  "\xe2\x8a\xb5\xcc\xb8\0" /* offset 5518 */
+  "\xe3\x80\x88\0" /* offset 5524 */
+  "\xe3\x80\x89\0" /* offset 5528 */
+  "\x31\x30\0" /* offset 5532 */
+  "\x31\x31\0" /* offset 5535 */
+  "\x31\x32\0" /* offset 5538 */
+  "\x31\x33\0" /* offset 5541 */
+  "\x31\x34\0" /* offset 5544 */
+  "\x31\x35\0" /* offset 5547 */
+  "\x31\x36\0" /* offset 5550 */
+  "\x31\x37\0" /* offset 5553 */
+  "\x31\x38\0" /* offset 5556 */
+  "\x31\x39\0" /* offset 5559 */
+  "\x32\x30\0" /* offset 5562 */
+  "\x28\x31\x29\0" /* offset 5565 */
+  "\x28\x32\x29\0" /* offset 5569 */
+  "\x28\x33\x29\0" /* offset 5573 */
+  "\x28\x34\x29\0" /* offset 5577 */
+  "\x28\x35\x29\0" /* offset 5581 */
+  "\x28\x36\x29\0" /* offset 5585 */
+  "\x28\x37\x29\0" /* offset 5589 */
+  "\x28\x38\x29\0" /* offset 5593 */
+  "\x28\x39\x29\0" /* offset 5597 */
+  "\x28\x31\x30\x29\0" /* offset 5601 */
+  "\x28\x31\x31\x29\0" /* offset 5606 */
+  "\x28\x31\x32\x29\0" /* offset 5611 */
+  "\x28\x31\x33\x29\0" /* offset 5616 */
+  "\x28\x31\x34\x29\0" /* offset 5621 */
+  "\x28\x31\x35\x29\0" /* offset 5626 */
+  "\x28\x31\x36\x29\0" /* offset 5631 */
+  "\x28\x31\x37\x29\0" /* offset 5636 */
+  "\x28\x31\x38\x29\0" /* offset 5641 */
+  "\x28\x31\x39\x29\0" /* offset 5646 */
+  "\x28\x32\x30\x29\0" /* offset 5651 */
+  "\x31\x2e\0" /* offset 5656 */
+  "\x32\x2e\0" /* offset 5659 */
+  "\x33\x2e\0" /* offset 5662 */
+  "\x34\x2e\0" /* offset 5665 */
+  "\x35\x2e\0" /* offset 5668 */
+  "\x36\x2e\0" /* offset 5671 */
+  "\x37\x2e\0" /* offset 5674 */
+  "\x38\x2e\0" /* offset 5677 */
+  "\x39\x2e\0" /* offset 5680 */
+  "\x31\x30\x2e\0" /* offset 5683 */
+  "\x31\x31\x2e\0" /* offset 5687 */
+  "\x31\x32\x2e\0" /* offset 5691 */
+  "\x31\x33\x2e\0" /* offset 5695 */
+  "\x31\x34\x2e\0" /* offset 5699 */
+  "\x31\x35\x2e\0" /* offset 5703 */
+  "\x31\x36\x2e\0" /* offset 5707 */
+  "\x31\x37\x2e\0" /* offset 5711 */
+  "\x31\x38\x2e\0" /* offset 5715 */
+  "\x31\x39\x2e\0" /* offset 5719 */
+  "\x32\x30\x2e\0" /* offset 5723 */
+  "\x28\x61\x29\0" /* offset 5727 */
+  "\x28\x62\x29\0" /* offset 5731 */
+  "\x28\x63\x29\0" /* offset 5735 */
+  "\x28\x64\x29\0" /* offset 5739 */
+  "\x28\x65\x29\0" /* offset 5743 */
+  "\x28\x66\x29\0" /* offset 5747 */
+  "\x28\x67\x29\0" /* offset 5751 */
+  "\x28\x68\x29\0" /* offset 5755 */
+  "\x28\x69\x29\0" /* offset 5759 */
+  "\x28\x6a\x29\0" /* offset 5763 */
+  "\x28\x6b\x29\0" /* offset 5767 */
+  "\x28\x6c\x29\0" /* offset 5771 */
+  "\x28\x6d\x29\0" /* offset 5775 */
+  "\x28\x6e\x29\0" /* offset 5779 */
+  "\x28\x6f\x29\0" /* offset 5783 */
+  "\x28\x70\x29\0" /* offset 5787 */
+  "\x28\x71\x29\0" /* offset 5791 */
+  "\x28\x72\x29\0" /* offset 5795 */
+  "\x28\x73\x29\0" /* offset 5799 */
+  "\x28\x74\x29\0" /* offset 5803 */
+  "\x28\x75\x29\0" /* offset 5807 */
+  "\x28\x76\x29\0" /* offset 5811 */
+  "\x28\x77\x29\0" /* offset 5815 */
+  "\x28\x78\x29\0" /* offset 5819 */
+  "\x28\x79\x29\0" /* offset 5823 */
+  "\x28\x7a\x29\0" /* offset 5827 */
+  "\x41\0" /* offset 5831 */
+  "\x47\0" /* offset 5833 */
+  "\x4a\0" /* offset 5835 */
+  "\x4f\0" /* offset 5837 */
+  "\x53\0" /* offset 5839 */
+  "\x54\0" /* offset 5841 */
+  "\x55\0" /* offset 5843 */
+  "\x57\0" /* offset 5845 */
+  "\x59\0" /* offset 5847 */
+  "\x62\0" /* offset 5849 */
+  "\x66\0" /* offset 5851 */
+  "\x6b\0" /* offset 5853 */
+  "\x70\0" /* offset 5855 */
+  "\x71\0" /* offset 5857 */
+  "\x74\0" /* offset 5859 */
+  "\x75\0" /* offset 5861 */
+  "\x7a\0" /* offset 5863 */
+  "\xe2\x88\xab\xe2\x88\xab\xe2\x88\xab\xe2\x88\xab\0" /* offset 5865 */
+  "\x3a\x3a\x3d\0" /* offset 5878 */
+  "\x3d\x3d\0" /* offset 5882 */
+  "\x3d\x3d\x3d\0" /* offset 5885 */
+  "\xe2\xab\x9d\xcc\xb8\0" /* offset 5889 */
+  "\xe6\xaf\x8d\0" /* offset 5895 */
+  "\xe9\xbe\x9f\0" /* offset 5899 */
+  "\xe4\xb8\x80\0" /* offset 5903 */
+  "\xe4\xb8\xa8\0" /* offset 5907 */
+  "\xe4\xb8\xb6\0" /* offset 5911 */
+  "\xe4\xb8\xbf\0" /* offset 5915 */
+  "\xe4\xb9\x99\0" /* offset 5919 */
+  "\xe4\xba\x85\0" /* offset 5923 */
+  "\xe4\xba\x8c\0" /* offset 5927 */
+  "\xe4\xba\xa0\0" /* offset 5931 */
+  "\xe4\xba\xba\0" /* offset 5935 */
+  "\xe5\x84\xbf\0" /* offset 5939 */
+  "\xe5\x85\xa5\0" /* offset 5943 */
+  "\xe5\x85\xab\0" /* offset 5947 */
+  "\xe5\x86\x82\0" /* offset 5951 */
+  "\xe5\x86\x96\0" /* offset 5955 */
+  "\xe5\x86\xab\0" /* offset 5959 */
+  "\xe5\x87\xa0\0" /* offset 5963 */
+  "\xe5\x87\xb5\0" /* offset 5967 */
+  "\xe5\x88\x80\0" /* offset 5971 */
+  "\xe5\x8a\x9b\0" /* offset 5975 */
+  "\xe5\x8b\xb9\0" /* offset 5979 */
+  "\xe5\x8c\x95\0" /* offset 5983 */
+  "\xe5\x8c\x9a\0" /* offset 5987 */
+  "\xe5\x8c\xb8\0" /* offset 5991 */
+  "\xe5\x8d\x81\0" /* offset 5995 */
+  "\xe5\x8d\x9c\0" /* offset 5999 */
+  "\xe5\x8d\xa9\0" /* offset 6003 */
+  "\xe5\x8e\x82\0" /* offset 6007 */
+  "\xe5\x8e\xb6\0" /* offset 6011 */
+  "\xe5\x8f\x88\0" /* offset 6015 */
+  "\xe5\x8f\xa3\0" /* offset 6019 */
+  "\xe5\x9b\x97\0" /* offset 6023 */
+  "\xe5\x9c\x9f\0" /* offset 6027 */
+  "\xe5\xa3\xab\0" /* offset 6031 */
+  "\xe5\xa4\x82\0" /* offset 6035 */
+  "\xe5\xa4\x8a\0" /* offset 6039 */
+  "\xe5\xa4\x95\0" /* offset 6043 */
+  "\xe5\xa4\xa7\0" /* offset 6047 */
+  "\xe5\xa5\xb3\0" /* offset 6051 */
+  "\xe5\xad\x90\0" /* offset 6055 */
+  "\xe5\xae\x80\0" /* offset 6059 */
+  "\xe5\xaf\xb8\0" /* offset 6063 */
+  "\xe5\xb0\x8f\0" /* offset 6067 */
+  "\xe5\xb0\xa2\0" /* offset 6071 */
+  "\xe5\xb0\xb8\0" /* offset 6075 */
+  "\xe5\xb1\xae\0" /* offset 6079 */
+  "\xe5\xb1\xb1\0" /* offset 6083 */
+  "\xe5\xb7\x9b\0" /* offset 6087 */
+  "\xe5\xb7\xa5\0" /* offset 6091 */
+  "\xe5\xb7\xb1\0" /* offset 6095 */
+  "\xe5\xb7\xbe\0" /* offset 6099 */
+  "\xe5\xb9\xb2\0" /* offset 6103 */
+  "\xe5\xb9\xba\0" /* offset 6107 */
+  "\xe5\xb9\xbf\0" /* offset 6111 */
+  "\xe5\xbb\xb4\0" /* offset 6115 */
+  "\xe5\xbb\xbe\0" /* offset 6119 */
+  "\xe5\xbc\x8b\0" /* offset 6123 */
+  "\xe5\xbc\x93\0" /* offset 6127 */
+  "\xe5\xbd\x90\0" /* offset 6131 */
+  "\xe5\xbd\xa1\0" /* offset 6135 */
+  "\xe5\xbd\xb3\0" /* offset 6139 */
+  "\xe5\xbf\x83\0" /* offset 6143 */
+  "\xe6\x88\x88\0" /* offset 6147 */
+  "\xe6\x88\xb6\0" /* offset 6151 */
+  "\xe6\x89\x8b\0" /* offset 6155 */
+  "\xe6\x94\xaf\0" /* offset 6159 */
+  "\xe6\x94\xb4\0" /* offset 6163 */
+  "\xe6\x96\x87\0" /* offset 6167 */
+  "\xe6\x96\x97\0" /* offset 6171 */
+  "\xe6\x96\xa4\0" /* offset 6175 */
+  "\xe6\x96\xb9\0" /* offset 6179 */
+  "\xe6\x97\xa0\0" /* offset 6183 */
+  "\xe6\x97\xa5\0" /* offset 6187 */
+  "\xe6\x9b\xb0\0" /* offset 6191 */
+  "\xe6\x9c\x88\0" /* offset 6195 */
+  "\xe6\x9c\xa8\0" /* offset 6199 */
+  "\xe6\xac\xa0\0" /* offset 6203 */
+  "\xe6\xad\xa2\0" /* offset 6207 */
+  "\xe6\xad\xb9\0" /* offset 6211 */
+  "\xe6\xae\xb3\0" /* offset 6215 */
+  "\xe6\xaf\x8b\0" /* offset 6219 */
+  "\xe6\xaf\x94\0" /* offset 6223 */
+  "\xe6\xaf\x9b\0" /* offset 6227 */
+  "\xe6\xb0\x8f\0" /* offset 6231 */
+  "\xe6\xb0\x94\0" /* offset 6235 */
+  "\xe6\xb0\xb4\0" /* offset 6239 */
+  "\xe7\x81\xab\0" /* offset 6243 */
+  "\xe7\x88\xaa\0" /* offset 6247 */
+  "\xe7\x88\xb6\0" /* offset 6251 */
+  "\xe7\x88\xbb\0" /* offset 6255 */
+  "\xe7\x88\xbf\0" /* offset 6259 */
+  "\xe7\x89\x87\0" /* offset 6263 */
+  "\xe7\x89\x99\0" /* offset 6267 */
+  "\xe7\x89\x9b\0" /* offset 6271 */
+  "\xe7\x8a\xac\0" /* offset 6275 */
+  "\xe7\x8e\x84\0" /* offset 6279 */
+  "\xe7\x8e\x89\0" /* offset 6283 */
+  "\xe7\x93\x9c\0" /* offset 6287 */
+  "\xe7\x93\xa6\0" /* offset 6291 */
+  "\xe7\x94\x98\0" /* offset 6295 */
+  "\xe7\x94\x9f\0" /* offset 6299 */
+  "\xe7\x94\xa8\0" /* offset 6303 */
+  "\xe7\x94\xb0\0" /* offset 6307 */
+  "\xe7\x96\x8b\0" /* offset 6311 */
+  "\xe7\x96\x92\0" /* offset 6315 */
+  "\xe7\x99\xb6\0" /* offset 6319 */
+  "\xe7\x99\xbd\0" /* offset 6323 */
+  "\xe7\x9a\xae\0" /* offset 6327 */
+  "\xe7\x9a\xbf\0" /* offset 6331 */
+  "\xe7\x9b\xae\0" /* offset 6335 */
+  "\xe7\x9f\x9b\0" /* offset 6339 */
+  "\xe7\x9f\xa2\0" /* offset 6343 */
+  "\xe7\x9f\xb3\0" /* offset 6347 */
+  "\xe7\xa4\xba\0" /* offset 6351 */
+  "\xe7\xa6\xb8\0" /* offset 6355 */
+  "\xe7\xa6\xbe\0" /* offset 6359 */
+  "\xe7\xa9\xb4\0" /* offset 6363 */
+  "\xe7\xab\x8b\0" /* offset 6367 */
+  "\xe7\xab\xb9\0" /* offset 6371 */
+  "\xe7\xb1\xb3\0" /* offset 6375 */
+  "\xe7\xb3\xb8\0" /* offset 6379 */
+  "\xe7\xbc\xb6\0" /* offset 6383 */
+  "\xe7\xbd\x91\0" /* offset 6387 */
+  "\xe7\xbe\x8a\0" /* offset 6391 */
+  "\xe7\xbe\xbd\0" /* offset 6395 */
+  "\xe8\x80\x81\0" /* offset 6399 */
+  "\xe8\x80\x8c\0" /* offset 6403 */
+  "\xe8\x80\x92\0" /* offset 6407 */
+  "\xe8\x80\xb3\0" /* offset 6411 */
+  "\xe8\x81\xbf\0" /* offset 6415 */
+  "\xe8\x82\x89\0" /* offset 6419 */
+  "\xe8\x87\xa3\0" /* offset 6423 */
+  "\xe8\x87\xaa\0" /* offset 6427 */
+  "\xe8\x87\xb3\0" /* offset 6431 */
+  "\xe8\x87\xbc\0" /* offset 6435 */
+  "\xe8\x88\x8c\0" /* offset 6439 */
+  "\xe8\x88\x9b\0" /* offset 6443 */
+  "\xe8\x88\x9f\0" /* offset 6447 */
+  "\xe8\x89\xae\0" /* offset 6451 */
+  "\xe8\x89\xb2\0" /* offset 6455 */
+  "\xe8\x89\xb8\0" /* offset 6459 */
+  "\xe8\x99\x8d\0" /* offset 6463 */
+  "\xe8\x99\xab\0" /* offset 6467 */
+  "\xe8\xa1\x80\0" /* offset 6471 */
+  "\xe8\xa1\x8c\0" /* offset 6475 */
+  "\xe8\xa1\xa3\0" /* offset 6479 */
+  "\xe8\xa5\xbe\0" /* offset 6483 */
+  "\xe8\xa6\x8b\0" /* offset 6487 */
+  "\xe8\xa7\x92\0" /* offset 6491 */
+  "\xe8\xa8\x80\0" /* offset 6495 */
+  "\xe8\xb0\xb7\0" /* offset 6499 */
+  "\xe8\xb1\x86\0" /* offset 6503 */
+  "\xe8\xb1\x95\0" /* offset 6507 */
+  "\xe8\xb1\xb8\0" /* offset 6511 */
+  "\xe8\xb2\x9d\0" /* offset 6515 */
+  "\xe8\xb5\xa4\0" /* offset 6519 */
+  "\xe8\xb5\xb0\0" /* offset 6523 */
+  "\xe8\xb6\xb3\0" /* offset 6527 */
+  "\xe8\xba\xab\0" /* offset 6531 */
+  "\xe8\xbb\x8a\0" /* offset 6535 */
+  "\xe8\xbe\x9b\0" /* offset 6539 */
+  "\xe8\xbe\xb0\0" /* offset 6543 */
+  "\xe8\xbe\xb5\0" /* offset 6547 */
+  "\xe9\x82\x91\0" /* offset 6551 */
+  "\xe9\x85\x89\0" /* offset 6555 */
+  "\xe9\x87\x86\0" /* offset 6559 */
+  "\xe9\x87\x8c\0" /* offset 6563 */
+  "\xe9\x87\x91\0" /* offset 6567 */
+  "\xe9\x95\xb7\0" /* offset 6571 */
+  "\xe9\x96\x80\0" /* offset 6575 */
+  "\xe9\x98\x9c\0" /* offset 6579 */
+  "\xe9\x9a\xb6\0" /* offset 6583 */
+  "\xe9\x9a\xb9\0" /* offset 6587 */
+  "\xe9\x9b\xa8\0" /* offset 6591 */
+  "\xe9\x9d\x91\0" /* offset 6595 */
+  "\xe9\x9d\x9e\0" /* offset 6599 */
+  "\xe9\x9d\xa2\0" /* offset 6603 */
+  "\xe9\x9d\xa9\0" /* offset 6607 */
+  "\xe9\x9f\x8b\0" /* offset 6611 */
+  "\xe9\x9f\xad\0" /* offset 6615 */
+  "\xe9\x9f\xb3\0" /* offset 6619 */
+  "\xe9\xa0\x81\0" /* offset 6623 */
+  "\xe9\xa2\xa8\0" /* offset 6627 */
+  "\xe9\xa3\x9b\0" /* offset 6631 */
+  "\xe9\xa3\x9f\0" /* offset 6635 */
+  "\xe9\xa6\x96\0" /* offset 6639 */
+  "\xe9\xa6\x99\0" /* offset 6643 */
+  "\xe9\xa6\xac\0" /* offset 6647 */
+  "\xe9\xaa\xa8\0" /* offset 6651 */
+  "\xe9\xab\x98\0" /* offset 6655 */
+  "\xe9\xab\x9f\0" /* offset 6659 */
+  "\xe9\xac\xa5\0" /* offset 6663 */
+  "\xe9\xac\xaf\0" /* offset 6667 */
+  "\xe9\xac\xb2\0" /* offset 6671 */
+  "\xe9\xac\xbc\0" /* offset 6675 */
+  "\xe9\xad\x9a\0" /* offset 6679 */
+  "\xe9\xb3\xa5\0" /* offset 6683 */
+  "\xe9\xb9\xb5\0" /* offset 6687 */
+  "\xe9\xb9\xbf\0" /* offset 6691 */
+  "\xe9\xba\xa5\0" /* offset 6695 */
+  "\xe9\xba\xbb\0" /* offset 6699 */
+  "\xe9\xbb\x83\0" /* offset 6703 */
+  "\xe9\xbb\x8d\0" /* offset 6707 */
+  "\xe9\xbb\x91\0" /* offset 6711 */
+  "\xe9\xbb\xb9\0" /* offset 6715 */
+  "\xe9\xbb\xbd\0" /* offset 6719 */
+  "\xe9\xbc\x8e\0" /* offset 6723 */
+  "\xe9\xbc\x93\0" /* offset 6727 */
+  "\xe9\xbc\xa0\0" /* offset 6731 */
+  "\xe9\xbc\xbb\0" /* offset 6735 */
+  "\xe9\xbd\x8a\0" /* offset 6739 */
+  "\xe9\xbd\x92\0" /* offset 6743 */
+  "\xe9\xbe\x8d\0" /* offset 6747 */
+  "\xe9\xbe\x9c\0" /* offset 6751 */
+  "\xe9\xbe\xa0\0" /* offset 6755 */
+  "\xe3\x80\x92\0" /* offset 6759 */
+  "\xe5\x8d\x84\0" /* offset 6763 */
+  "\xe5\x8d\x85\0" /* offset 6767 */
+  "\xe3\x81\x8b\xe3\x82\x99\0" /* offset 6771 */
+  "\xe3\x81\x8d\xe3\x82\x99\0" /* offset 6778 */
+  "\xe3\x81\x8f\xe3\x82\x99\0" /* offset 6785 */
+  "\xe3\x81\x91\xe3\x82\x99\0" /* offset 6792 */
+  "\xe3\x81\x93\xe3\x82\x99\0" /* offset 6799 */
+  "\xe3\x81\x95\xe3\x82\x99\0" /* offset 6806 */
+  "\xe3\x81\x97\xe3\x82\x99\0" /* offset 6813 */
+  "\xe3\x81\x99\xe3\x82\x99\0" /* offset 6820 */
+  "\xe3\x81\x9b\xe3\x82\x99\0" /* offset 6827 */
+  "\xe3\x81\x9d\xe3\x82\x99\0" /* offset 6834 */
+  "\xe3\x81\x9f\xe3\x82\x99\0" /* offset 6841 */
+  "\xe3\x81\xa1\xe3\x82\x99\0" /* offset 6848 */
+  "\xe3\x81\xa4\xe3\x82\x99\0" /* offset 6855 */
+  "\xe3\x81\xa6\xe3\x82\x99\0" /* offset 6862 */
+  "\xe3\x81\xa8\xe3\x82\x99\0" /* offset 6869 */
+  "\xe3\x81\xaf\xe3\x82\x99\0" /* offset 6876 */
+  "\xe3\x81\xaf\xe3\x82\x9a\0" /* offset 6883 */
+  "\xe3\x81\xb2\xe3\x82\x99\0" /* offset 6890 */
+  "\xe3\x81\xb2\xe3\x82\x9a\0" /* offset 6897 */
+  "\xe3\x81\xb5\xe3\x82\x99\0" /* offset 6904 */
+  "\xe3\x81\xb5\xe3\x82\x9a\0" /* offset 6911 */
+  "\xe3\x81\xb8\xe3\x82\x99\0" /* offset 6918 */
+  "\xe3\x81\xb8\xe3\x82\x9a\0" /* offset 6925 */
+  "\xe3\x81\xbb\xe3\x82\x99\0" /* offset 6932 */
+  "\xe3\x81\xbb\xe3\x82\x9a\0" /* offset 6939 */
+  "\xe3\x81\x86\xe3\x82\x99\0" /* offset 6946 */
+  "\x20\xe3\x82\x99\0" /* offset 6953 */
+  "\x20\xe3\x82\x9a\0" /* offset 6958 */
+  "\xe3\x82\x9d\xe3\x82\x99\0" /* offset 6963 */
+  "\xe3\x82\x88\xe3\x82\x8a\0" /* offset 6970 */
+  "\xe3\x82\xab\xe3\x82\x99\0" /* offset 6977 */
+  "\xe3\x82\xad\xe3\x82\x99\0" /* offset 6984 */
+  "\xe3\x82\xaf\xe3\x82\x99\0" /* offset 6991 */
+  "\xe3\x82\xb1\xe3\x82\x99\0" /* offset 6998 */
+  "\xe3\x82\xb3\xe3\x82\x99\0" /* offset 7005 */
+  "\xe3\x82\xb5\xe3\x82\x99\0" /* offset 7012 */
+  "\xe3\x82\xb7\xe3\x82\x99\0" /* offset 7019 */
+  "\xe3\x82\xb9\xe3\x82\x99\0" /* offset 7026 */
+  "\xe3\x82\xbb\xe3\x82\x99\0" /* offset 7033 */
+  "\xe3\x82\xbd\xe3\x82\x99\0" /* offset 7040 */
+  "\xe3\x82\xbf\xe3\x82\x99\0" /* offset 7047 */
+  "\xe3\x83\x81\xe3\x82\x99\0" /* offset 7054 */
+  "\xe3\x83\x84\xe3\x82\x99\0" /* offset 7061 */
+  "\xe3\x83\x86\xe3\x82\x99\0" /* offset 7068 */
+  "\xe3\x83\x88\xe3\x82\x99\0" /* offset 7075 */
+  "\xe3\x83\x8f\xe3\x82\x99\0" /* offset 7082 */
+  "\xe3\x83\x8f\xe3\x82\x9a\0" /* offset 7089 */
+  "\xe3\x83\x92\xe3\x82\x99\0" /* offset 7096 */
+  "\xe3\x83\x92\xe3\x82\x9a\0" /* offset 7103 */
+  "\xe3\x83\x95\xe3\x82\x99\0" /* offset 7110 */
+  "\xe3\x83\x95\xe3\x82\x9a\0" /* offset 7117 */
+  "\xe3\x83\x98\xe3\x82\x99\0" /* offset 7124 */
+  "\xe3\x83\x98\xe3\x82\x9a\0" /* offset 7131 */
+  "\xe3\x83\x9b\xe3\x82\x99\0" /* offset 7138 */
+  "\xe3\x83\x9b\xe3\x82\x9a\0" /* offset 7145 */
+  "\xe3\x82\xa6\xe3\x82\x99\0" /* offset 7152 */
+  "\xe3\x83\xaf\xe3\x82\x99\0" /* offset 7159 */
+  "\xe3\x83\xb0\xe3\x82\x99\0" /* offset 7166 */
+  "\xe3\x83\xb1\xe3\x82\x99\0" /* offset 7173 */
+  "\xe3\x83\xb2\xe3\x82\x99\0" /* offset 7180 */
+  "\xe3\x83\xbd\xe3\x82\x99\0" /* offset 7187 */
+  "\xe3\x82\xb3\xe3\x83\x88\0" /* offset 7194 */
+  "\xe1\x84\x80\0" /* offset 7201 */
+  "\xe1\x84\x81\0" /* offset 7205 */
+  "\xe1\x86\xaa\0" /* offset 7209 */
+  "\xe1\x84\x82\0" /* offset 7213 */
+  "\xe1\x86\xac\0" /* offset 7217 */
+  "\xe1\x86\xad\0" /* offset 7221 */
+  "\xe1\x84\x83\0" /* offset 7225 */
+  "\xe1\x84\x84\0" /* offset 7229 */
+  "\xe1\x84\x85\0" /* offset 7233 */
+  "\xe1\x86\xb0\0" /* offset 7237 */
+  "\xe1\x86\xb1\0" /* offset 7241 */
+  "\xe1\x86\xb2\0" /* offset 7245 */
+  "\xe1\x86\xb3\0" /* offset 7249 */
+  "\xe1\x86\xb4\0" /* offset 7253 */
+  "\xe1\x86\xb5\0" /* offset 7257 */
+  "\xe1\x84\x9a\0" /* offset 7261 */
+  "\xe1\x84\x86\0" /* offset 7265 */
+  "\xe1\x84\x87\0" /* offset 7269 */
+  "\xe1\x84\x88\0" /* offset 7273 */
+  "\xe1\x84\xa1\0" /* offset 7277 */
+  "\xe1\x84\x89\0" /* offset 7281 */
+  "\xe1\x84\x8a\0" /* offset 7285 */
+  "\xe1\x84\x8b\0" /* offset 7289 */
+  "\xe1\x84\x8c\0" /* offset 7293 */
+  "\xe1\x84\x8d\0" /* offset 7297 */
+  "\xe1\x84\x8e\0" /* offset 7301 */
+  "\xe1\x84\x8f\0" /* offset 7305 */
+  "\xe1\x84\x90\0" /* offset 7309 */
+  "\xe1\x84\x91\0" /* offset 7313 */
+  "\xe1\x84\x92\0" /* offset 7317 */
+  "\xe1\x85\xa1\0" /* offset 7321 */
+  "\xe1\x85\xa2\0" /* offset 7325 */
+  "\xe1\x85\xa3\0" /* offset 7329 */
+  "\xe1\x85\xa4\0" /* offset 7333 */
+  "\xe1\x85\xa5\0" /* offset 7337 */
+  "\xe1\x85\xa6\0" /* offset 7341 */
+  "\xe1\x85\xa7\0" /* offset 7345 */
+  "\xe1\x85\xa8\0" /* offset 7349 */
+  "\xe1\x85\xa9\0" /* offset 7353 */
+  "\xe1\x85\xaa\0" /* offset 7357 */
+  "\xe1\x85\xab\0" /* offset 7361 */
+  "\xe1\x85\xac\0" /* offset 7365 */
+  "\xe1\x85\xad\0" /* offset 7369 */
+  "\xe1\x85\xae\0" /* offset 7373 */
+  "\xe1\x85\xaf\0" /* offset 7377 */
+  "\xe1\x85\xb0\0" /* offset 7381 */
+  "\xe1\x85\xb1\0" /* offset 7385 */
+  "\xe1\x85\xb2\0" /* offset 7389 */
+  "\xe1\x85\xb3\0" /* offset 7393 */
+  "\xe1\x85\xb4\0" /* offset 7397 */
+  "\xe1\x85\xb5\0" /* offset 7401 */
+  "\xe1\x85\xa0\0" /* offset 7405 */
+  "\xe1\x84\x94\0" /* offset 7409 */
+  "\xe1\x84\x95\0" /* offset 7413 */
+  "\xe1\x87\x87\0" /* offset 7417 */
+  "\xe1\x87\x88\0" /* offset 7421 */
+  "\xe1\x87\x8c\0" /* offset 7425 */
+  "\xe1\x87\x8e\0" /* offset 7429 */
+  "\xe1\x87\x93\0" /* offset 7433 */
+  "\xe1\x87\x97\0" /* offset 7437 */
+  "\xe1\x87\x99\0" /* offset 7441 */
+  "\xe1\x84\x9c\0" /* offset 7445 */
+  "\xe1\x87\x9d\0" /* offset 7449 */
+  "\xe1\x87\x9f\0" /* offset 7453 */
+  "\xe1\x84\x9d\0" /* offset 7457 */
+  "\xe1\x84\x9e\0" /* offset 7461 */
+  "\xe1\x84\xa0\0" /* offset 7465 */
+  "\xe1\x84\xa2\0" /* offset 7469 */
+  "\xe1\x84\xa3\0" /* offset 7473 */
+  "\xe1\x84\xa7\0" /* offset 7477 */
+  "\xe1\x84\xa9\0" /* offset 7481 */
+  "\xe1\x84\xab\0" /* offset 7485 */
+  "\xe1\x84\xac\0" /* offset 7489 */
+  "\xe1\x84\xad\0" /* offset 7493 */
+  "\xe1\x84\xae\0" /* offset 7497 */
+  "\xe1\x84\xaf\0" /* offset 7501 */
+  "\xe1\x84\xb2\0" /* offset 7505 */
+  "\xe1\x84\xb6\0" /* offset 7509 */
+  "\xe1\x85\x80\0" /* offset 7513 */
+  "\xe1\x85\x87\0" /* offset 7517 */
+  "\xe1\x85\x8c\0" /* offset 7521 */
+  "\xe1\x87\xb1\0" /* offset 7525 */
+  "\xe1\x87\xb2\0" /* offset 7529 */
+  "\xe1\x85\x97\0" /* offset 7533 */
+  "\xe1\x85\x98\0" /* offset 7537 */
+  "\xe1\x85\x99\0" /* offset 7541 */
+  "\xe1\x86\x84\0" /* offset 7545 */
+  "\xe1\x86\x85\0" /* offset 7549 */
+  "\xe1\x86\x88\0" /* offset 7553 */
+  "\xe1\x86\x91\0" /* offset 7557 */
+  "\xe1\x86\x92\0" /* offset 7561 */
+  "\xe1\x86\x94\0" /* offset 7565 */
+  "\xe1\x86\x9e\0" /* offset 7569 */
+  "\xe1\x86\xa1\0" /* offset 7573 */
+  "\xe4\xb8\x89\0" /* offset 7577 */
+  "\xe5\x9b\x9b\0" /* offset 7581 */
+  "\xe4\xb8\x8a\0" /* offset 7585 */
+  "\xe4\xb8\xad\0" /* offset 7589 */
+  "\xe4\xb8\x8b\0" /* offset 7593 */
+  "\xe7\x94\xb2\0" /* offset 7597 */
+  "\xe4\xb8\x99\0" /* offset 7601 */
+  "\xe4\xb8\x81\0" /* offset 7605 */
+  "\xe5\xa4\xa9\0" /* offset 7609 */
+  "\xe5\x9c\xb0\0" /* offset 7613 */
+  "\x28\xe1\x84\x80\x29\0" /* offset 7617 */
+  "\x28\xe1\x84\x82\x29\0" /* offset 7623 */
+  "\x28\xe1\x84\x83\x29\0" /* offset 7629 */
+  "\x28\xe1\x84\x85\x29\0" /* offset 7635 */
+  "\x28\xe1\x84\x86\x29\0" /* offset 7641 */
+  "\x28\xe1\x84\x87\x29\0" /* offset 7647 */
+  "\x28\xe1\x84\x89\x29\0" /* offset 7653 */
+  "\x28\xe1\x84\x8b\x29\0" /* offset 7659 */
+  "\x28\xe1\x84\x8c\x29\0" /* offset 7665 */
+  "\x28\xe1\x84\x8e\x29\0" /* offset 7671 */
+  "\x28\xe1\x84\x8f\x29\0" /* offset 7677 */
+  "\x28\xe1\x84\x90\x29\0" /* offset 7683 */
+  "\x28\xe1\x84\x91\x29\0" /* offset 7689 */
+  "\x28\xe1\x84\x92\x29\0" /* offset 7695 */
+  "\x28\xe1\x84\x80\xe1\x85\xa1\x29\0" /* offset 7701 */
+  "\x28\xe1\x84\x82\xe1\x85\xa1\x29\0" /* offset 7710 */
+  "\x28\xe1\x84\x83\xe1\x85\xa1\x29\0" /* offset 7719 */
+  "\x28\xe1\x84\x85\xe1\x85\xa1\x29\0" /* offset 7728 */
+  "\x28\xe1\x84\x86\xe1\x85\xa1\x29\0" /* offset 7737 */
+  "\x28\xe1\x84\x87\xe1\x85\xa1\x29\0" /* offset 7746 */
+  "\x28\xe1\x84\x89\xe1\x85\xa1\x29\0" /* offset 7755 */
+  "\x28\xe1\x84\x8b\xe1\x85\xa1\x29\0" /* offset 7764 */
+  "\x28\xe1\x84\x8c\xe1\x85\xa1\x29\0" /* offset 7773 */
+  "\x28\xe1\x84\x8e\xe1\x85\xa1\x29\0" /* offset 7782 */
+  "\x28\xe1\x84\x8f\xe1\x85\xa1\x29\0" /* offset 7791 */
+  "\x28\xe1\x84\x90\xe1\x85\xa1\x29\0" /* offset 7800 */
+  "\x28\xe1\x84\x91\xe1\x85\xa1\x29\0" /* offset 7809 */
+  "\x28\xe1\x84\x92\xe1\x85\xa1\x29\0" /* offset 7818 */
+  "\x28\xe1\x84\x8c\xe1\x85\xae\x29\0" /* offset 7827 */
+  "\x28\xe4\xb8\x80\x29\0" /* offset 7836 */
+  "\x28\xe4\xba\x8c\x29\0" /* offset 7842 */
+  "\x28\xe4\xb8\x89\x29\0" /* offset 7848 */
+  "\x28\xe5\x9b\x9b\x29\0" /* offset 7854 */
+  "\x28\xe4\xba\x94\x29\0" /* offset 7860 */
+  "\x28\xe5\x85\xad\x29\0" /* offset 7866 */
+  "\x28\xe4\xb8\x83\x29\0" /* offset 7872 */
+  "\x28\xe5\x85\xab\x29\0" /* offset 7878 */
+  "\x28\xe4\xb9\x9d\x29\0" /* offset 7884 */
+  "\x28\xe5\x8d\x81\x29\0" /* offset 7890 */
+  "\x28\xe6\x9c\x88\x29\0" /* offset 7896 */
+  "\x28\xe7\x81\xab\x29\0" /* offset 7902 */
+  "\x28\xe6\xb0\xb4\x29\0" /* offset 7908 */
+  "\x28\xe6\x9c\xa8\x29\0" /* offset 7914 */
+  "\x28\xe9\x87\x91\x29\0" /* offset 7920 */
+  "\x28\xe5\x9c\x9f\x29\0" /* offset 7926 */
+  "\x28\xe6\x97\xa5\x29\0" /* offset 7932 */
+  "\x28\xe6\xa0\xaa\x29\0" /* offset 7938 */
+  "\x28\xe6\x9c\x89\x29\0" /* offset 7944 */
+  "\x28\xe7\xa4\xbe\x29\0" /* offset 7950 */
+  "\x28\xe5\x90\x8d\x29\0" /* offset 7956 */
+  "\x28\xe7\x89\xb9\x29\0" /* offset 7962 */
+  "\x28\xe8\xb2\xa1\x29\0" /* offset 7968 */
+  "\x28\xe7\xa5\x9d\x29\0" /* offset 7974 */
+  "\x28\xe5\x8a\xb4\x29\0" /* offset 7980 */
+  "\x28\xe4\xbb\xa3\x29\0" /* offset 7986 */
+  "\x28\xe5\x91\xbc\x29\0" /* offset 7992 */
+  "\x28\xe5\xad\xa6\x29\0" /* offset 7998 */
+  "\x28\xe7\x9b\xa3\x29\0" /* offset 8004 */
+  "\x28\xe4\xbc\x81\x29\0" /* offset 8010 */
+  "\x28\xe8\xb3\x87\x29\0" /* offset 8016 */
+  "\x28\xe5\x8d\x94\x29\0" /* offset 8022 */
+  "\x28\xe7\xa5\xad\x29\0" /* offset 8028 */
+  "\x28\xe4\xbc\x91\x29\0" /* offset 8034 */
+  "\x28\xe8\x87\xaa\x29\0" /* offset 8040 */
+  "\x28\xe8\x87\xb3\x29\0" /* offset 8046 */
+  "\x32\x31\0" /* offset 8052 */
+  "\x32\x32\0" /* offset 8055 */
+  "\x32\x33\0" /* offset 8058 */
+  "\x32\x34\0" /* offset 8061 */
+  "\x32\x35\0" /* offset 8064 */
+  "\x32\x36\0" /* offset 8067 */
+  "\x32\x37\0" /* offset 8070 */
+  "\x32\x38\0" /* offset 8073 */
+  "\x32\x39\0" /* offset 8076 */
+  "\x33\x30\0" /* offset 8079 */
+  "\x33\x31\0" /* offset 8082 */
+  "\x33\x32\0" /* offset 8085 */
+  "\x33\x33\0" /* offset 8088 */
+  "\x33\x34\0" /* offset 8091 */
+  "\x33\x35\0" /* offset 8094 */
+  "\xe1\x84\x80\xe1\x85\xa1\0" /* offset 8097 */
+  "\xe1\x84\x82\xe1\x85\xa1\0" /* offset 8104 */
+  "\xe1\x84\x83\xe1\x85\xa1\0" /* offset 8111 */
+  "\xe1\x84\x85\xe1\x85\xa1\0" /* offset 8118 */
+  "\xe1\x84\x86\xe1\x85\xa1\0" /* offset 8125 */
+  "\xe1\x84\x87\xe1\x85\xa1\0" /* offset 8132 */
+  "\xe1\x84\x89\xe1\x85\xa1\0" /* offset 8139 */
+  "\xe1\x84\x8b\xe1\x85\xa1\0" /* offset 8146 */
+  "\xe1\x84\x8c\xe1\x85\xa1\0" /* offset 8153 */
+  "\xe1\x84\x8e\xe1\x85\xa1\0" /* offset 8160 */
+  "\xe1\x84\x8f\xe1\x85\xa1\0" /* offset 8167 */
+  "\xe1\x84\x90\xe1\x85\xa1\0" /* offset 8174 */
+  "\xe1\x84\x91\xe1\x85\xa1\0" /* offset 8181 */
+  "\xe1\x84\x92\xe1\x85\xa1\0" /* offset 8188 */
+  "\xe4\xba\x94\0" /* offset 8195 */
+  "\xe5\x85\xad\0" /* offset 8199 */
+  "\xe4\xb8\x83\0" /* offset 8203 */
+  "\xe4\xb9\x9d\0" /* offset 8207 */
+  "\xe6\xa0\xaa\0" /* offset 8211 */
+  "\xe6\x9c\x89\0" /* offset 8215 */
+  "\xe7\xa4\xbe\0" /* offset 8219 */
+  "\xe5\x90\x8d\0" /* offset 8223 */
+  "\xe7\x89\xb9\0" /* offset 8227 */
+  "\xe8\xb2\xa1\0" /* offset 8231 */
+  "\xe7\xa5\x9d\0" /* offset 8235 */
+  "\xe5\x8a\xb4\0" /* offset 8239 */
+  "\xe7\xa7\x98\0" /* offset 8243 */
+  "\xe7\x94\xb7\0" /* offset 8247 */
+  "\xe9\x81\xa9\0" /* offset 8251 */
+  "\xe5\x84\xaa\0" /* offset 8255 */
+  "\xe5\x8d\xb0\0" /* offset 8259 */
+  "\xe6\xb3\xa8\0" /* offset 8263 */
+  "\xe9\xa0\x85\0" /* offset 8267 */
+  "\xe4\xbc\x91\0" /* offset 8271 */
+  "\xe5\x86\x99\0" /* offset 8275 */
+  "\xe6\xad\xa3\0" /* offset 8279 */
+  "\xe5\xb7\xa6\0" /* offset 8283 */
+  "\xe5\x8f\xb3\0" /* offset 8287 */
+  "\xe5\x8c\xbb\0" /* offset 8291 */
+  "\xe5\xae\x97\0" /* offset 8295 */
+  "\xe5\xad\xa6\0" /* offset 8299 */
+  "\xe7\x9b\xa3\0" /* offset 8303 */
+  "\xe4\xbc\x81\0" /* offset 8307 */
+  "\xe8\xb3\x87\0" /* offset 8311 */
+  "\xe5\x8d\x94\0" /* offset 8315 */
+  "\xe5\xa4\x9c\0" /* offset 8319 */
+  "\x33\x36\0" /* offset 8323 */
+  "\x33\x37\0" /* offset 8326 */
+  "\x33\x38\0" /* offset 8329 */
+  "\x33\x39\0" /* offset 8332 */
+  "\x34\x30\0" /* offset 8335 */
+  "\x34\x31\0" /* offset 8338 */
+  "\x34\x32\0" /* offset 8341 */
+  "\x34\x33\0" /* offset 8344 */
+  "\x34\x34\0" /* offset 8347 */
+  "\x34\x35\0" /* offset 8350 */
+  "\x34\x36\0" /* offset 8353 */
+  "\x34\x37\0" /* offset 8356 */
+  "\x34\x38\0" /* offset 8359 */
+  "\x34\x39\0" /* offset 8362 */
+  "\x35\x30\0" /* offset 8365 */
+  "\x31\xe6\x9c\x88\0" /* offset 8368 */
+  "\x32\xe6\x9c\x88\0" /* offset 8373 */
+  "\x33\xe6\x9c\x88\0" /* offset 8378 */
+  "\x34\xe6\x9c\x88\0" /* offset 8383 */
+  "\x35\xe6\x9c\x88\0" /* offset 8388 */
+  "\x36\xe6\x9c\x88\0" /* offset 8393 */
+  "\x37\xe6\x9c\x88\0" /* offset 8398 */
+  "\x38\xe6\x9c\x88\0" /* offset 8403 */
+  "\x39\xe6\x9c\x88\0" /* offset 8408 */
+  "\x31\x30\xe6\x9c\x88\0" /* offset 8413 */
+  "\x31\x31\xe6\x9c\x88\0" /* offset 8419 */
+  "\x31\x32\xe6\x9c\x88\0" /* offset 8425 */
+  "\xe3\x82\xa2\0" /* offset 8431 */
+  "\xe3\x82\xa4\0" /* offset 8435 */
+  "\xe3\x82\xa6\0" /* offset 8439 */
+  "\xe3\x82\xa8\0" /* offset 8443 */
+  "\xe3\x82\xaa\0" /* offset 8447 */
+  "\xe3\x82\xab\0" /* offset 8451 */
+  "\xe3\x82\xad\0" /* offset 8455 */
+  "\xe3\x82\xaf\0" /* offset 8459 */
+  "\xe3\x82\xb1\0" /* offset 8463 */
+  "\xe3\x82\xb3\0" /* offset 8467 */
+  "\xe3\x82\xb5\0" /* offset 8471 */
+  "\xe3\x82\xb7\0" /* offset 8475 */
+  "\xe3\x82\xb9\0" /* offset 8479 */
+  "\xe3\x82\xbb\0" /* offset 8483 */
+  "\xe3\x82\xbd\0" /* offset 8487 */
+  "\xe3\x82\xbf\0" /* offset 8491 */
+  "\xe3\x83\x81\0" /* offset 8495 */
+  "\xe3\x83\x84\0" /* offset 8499 */
+  "\xe3\x83\x86\0" /* offset 8503 */
+  "\xe3\x83\x88\0" /* offset 8507 */
+  "\xe3\x83\x8a\0" /* offset 8511 */
+  "\xe3\x83\x8b\0" /* offset 8515 */
+  "\xe3\x83\x8c\0" /* offset 8519 */
+  "\xe3\x83\x8d\0" /* offset 8523 */
+  "\xe3\x83\x8e\0" /* offset 8527 */
+  "\xe3\x83\x8f\0" /* offset 8531 */
+  "\xe3\x83\x92\0" /* offset 8535 */
+  "\xe3\x83\x95\0" /* offset 8539 */
+  "\xe3\x83\x98\0" /* offset 8543 */
+  "\xe3\x83\x9b\0" /* offset 8547 */
+  "\xe3\x83\x9e\0" /* offset 8551 */
+  "\xe3\x83\x9f\0" /* offset 8555 */
+  "\xe3\x83\xa0\0" /* offset 8559 */
+  "\xe3\x83\xa1\0" /* offset 8563 */
+  "\xe3\x83\xa2\0" /* offset 8567 */
+  "\xe3\x83\xa4\0" /* offset 8571 */
+  "\xe3\x83\xa6\0" /* offset 8575 */
+  "\xe3\x83\xa8\0" /* offset 8579 */
+  "\xe3\x83\xa9\0" /* offset 8583 */
+  "\xe3\x83\xaa\0" /* offset 8587 */
+  "\xe3\x83\xab\0" /* offset 8591 */
+  "\xe3\x83\xac\0" /* offset 8595 */
+  "\xe3\x83\xad\0" /* offset 8599 */
+  "\xe3\x83\xaf\0" /* offset 8603 */
+  "\xe3\x83\xb0\0" /* offset 8607 */
+  "\xe3\x83\xb1\0" /* offset 8611 */
+  "\xe3\x83\xb2\0" /* offset 8615 */
+  "\xe3\x82\xa2\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x88\0" /* offset 8619 */
+  "\xe3\x82\xa2\xe3\x83\xab\xe3\x83\x95\xe3\x82\xa1\0" /* offset 8635 */
+  "\xe3\x82\xa2\xe3\x83\xb3\xe3\x83\x98\xe3\x82\x9a\xe3\x82\xa2\0" /* offset 8648 */
+  "\xe3\x82\xa2\xe3\x83\xbc\xe3\x83\xab\0" /* offset 8664 */
+  "\xe3\x82\xa4\xe3\x83\x8b\xe3\x83\xb3\xe3\x82\xaf\xe3\x82\x99\0" /* offset 8674 */
+  "\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x81\0" /* offset 8690 */
+  "\xe3\x82\xa6\xe3\x82\xa9\xe3\x83\xb3\0" /* offset 8700 */
+  "\xe3\x82\xa8\xe3\x82\xb9\xe3\x82\xaf\xe3\x83\xbc\xe3\x83\x88\xe3\x82\x99\0" /* offset 8710 */
+  "\xe3\x82\xa8\xe3\x83\xbc\xe3\x82\xab\xe3\x83\xbc\0" /* offset 8729 */
+  "\xe3\x82\xaa\xe3\x83\xb3\xe3\x82\xb9\0" /* offset 8742 */
+  "\xe3\x82\xaa\xe3\x83\xbc\xe3\x83\xa0\0" /* offset 8752 */
+  "\xe3\x82\xab\xe3\x82\xa4\xe3\x83\xaa\0" /* offset 8762 */
+  "\xe3\x82\xab\xe3\x83\xa9\xe3\x83\x83\xe3\x83\x88\0" /* offset 8772 */
+  "\xe3\x82\xab\xe3\x83\xad\xe3\x83\xaa\xe3\x83\xbc\0" /* offset 8785 */
+  "\xe3\x82\xab\xe3\x82\x99\xe3\x83\xad\xe3\x83\xb3\0" /* offset 8798 */
+  "\xe3\x82\xab\xe3\x82\x99\xe3\x83\xb3\xe3\x83\x9e\0" /* offset 8811 */
+  "\xe3\x82\xad\xe3\x82\x99\xe3\x82\xab\xe3\x82\x99\0" /* offset 8824 */
+  "\xe3\x82\xad\xe3\x82\x99\xe3\x83\x8b\xe3\x83\xbc\0" /* offset 8837 */
+  "\xe3\x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x83\xbc\0" /* offset 8850 */
+  "\xe3\x82\xad\xe3\x82\x99\xe3\x83\xab\xe3\x82\xbf\xe3\x82\x99\xe3\x83\xbc\0" /* offset 8863 */
+  "\xe3\x82\xad\xe3\x83\xad\0" /* offset 8882 */
+  "\xe3\x82\xad\xe3\x83\xad\xe3\x82\xaf\xe3\x82\x99\xe3\x83\xa9\xe3\x83\xa0\0" /* offset 8889 */
+  "\xe3\x82\xad\xe3\x83\xad\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88\xe3\x83\xab\0" /* offset 8908 */
+  "\xe3\x82\xad\xe3\x83\xad\xe3\x83\xaf\xe3\x83\x83\xe3\x83\x88\0" /* offset 8927 */
+  "\xe3\x82\xaf\xe3\x82\x99\xe3\x83\xa9\xe3\x83\xa0\0" /* offset 8943 */
+  "\xe3\x82\xaf\xe3\x82\x99\xe3\x83\xa9\xe3\x83\xa0\xe3\x83\x88\xe3\x83\xb3\0" /* offset 8956 */
+  "\xe3\x82\xaf\xe3\x83\xab\xe3\x82\xbb\xe3\x82\x99\xe3\x82\xa4\xe3\x83\xad\0" /* offset 8975 */
+  "\xe3\x82\xaf\xe3\x83\xad\xe3\x83\xbc\xe3\x83\x8d\0" /* offset 8994 */
+  "\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb9\0" /* offset 9007 */
+  "\xe3\x82\xb3\xe3\x83\xab\xe3\x83\x8a\0" /* offset 9017 */
+  "\xe3\x82\xb3\xe3\x83\xbc\xe3\x83\x9b\xe3\x82\x9a\0" /* offset 9027 */
+  "\xe3\x82\xb5\xe3\x82\xa4\xe3\x82\xaf\xe3\x83\xab\0" /* offset 9040 */
+  "\xe3\x82\xb5\xe3\x83\xb3\xe3\x83\x81\xe3\x83\xbc\xe3\x83\xa0\0" /* offset 9053 */
+  "\xe3\x82\xb7\xe3\x83\xaa\xe3\x83\xb3\xe3\x82\xaf\xe3\x82\x99\0" /* offset 9069 */
+  "\xe3\x82\xbb\xe3\x83\xb3\xe3\x83\x81\0" /* offset 9085 */
+  "\xe3\x82\xbb\xe3\x83\xb3\xe3\x83\x88\0" /* offset 9095 */
+  "\xe3\x82\xbf\xe3\x82\x99\xe3\x83\xbc\xe3\x82\xb9\0" /* offset 9105 */
+  "\xe3\x83\x86\xe3\x82\x99\xe3\x82\xb7\0" /* offset 9118 */
+  "\xe3\x83\x88\xe3\x82\x99\xe3\x83\xab\0" /* offset 9128 */
+  "\xe3\x83\x88\xe3\x83\xb3\0" /* offset 9138 */
+  "\xe3\x83\x8a\xe3\x83\x8e\0" /* offset 9145 */
+  "\xe3\x83\x8e\xe3\x83\x83\xe3\x83\x88\0" /* offset 9152 */
+  "\xe3\x83\x8f\xe3\x82\xa4\xe3\x83\x84\0" /* offset 9162 */
+  "\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x82\xbb\xe3\x83\xb3\xe3\x83\x88\0" /* offset 9172 */
+  "\xe3\x83\x8f\xe3\x82\x9a\xe3\x83\xbc\xe3\x83\x84\0" /* offset 9191 */
+  "\xe3\x83\x8f\xe3\x82\x99\xe3\x83\xbc\xe3\x83\xac\xe3\x83\xab\0" /* offset 9204 */
+  "\xe3\x83\x92\xe3\x82\x9a\xe3\x82\xa2\xe3\x82\xb9\xe3\x83\x88\xe3\x83\xab\0" /* offset 9220 */
+  "\xe3\x83\x92\xe3\x82\x9a\xe3\x82\xaf\xe3\x83\xab\0" /* offset 9239 */
+  "\xe3\x83\x92\xe3\x82\x9a\xe3\x82\xb3\0" /* offset 9252 */
+  "\xe3\x83\x92\xe3\x82\x99\xe3\x83\xab\0" /* offset 9262 */
+  "\xe3\x83\x95\xe3\x82\xa1\xe3\x83\xa9\xe3\x83\x83\xe3\x83\x88\xe3\x82\x99\0" /* offset 9272 */
+  "\xe3\x83\x95\xe3\x82\xa3\xe3\x83\xbc\xe3\x83\x88\0" /* offset 9291 */
+  "\xe3\x83\x95\xe3\x82\x99\xe3\x83\x83\xe3\x82\xb7\xe3\x82\xa7\xe3\x83\xab\0" /* offset 9304 */
+  "\xe3\x83\x95\xe3\x83\xa9\xe3\x83\xb3\0" /* offset 9323 */
+  "\xe3\x83\x98\xe3\x82\xaf\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\xab\0" /* offset 9333 */
+  "\xe3\x83\x98\xe3\x82\x9a\xe3\x82\xbd\0" /* offset 9349 */
+  "\xe3\x83\x98\xe3\x82\x9a\xe3\x83\x8b\xe3\x83\x92\0" /* offset 9359 */
+  "\xe3\x83\x98\xe3\x83\xab\xe3\x83\x84\0" /* offset 9372 */
+  "\xe3\x83\x98\xe3\x82\x9a\xe3\x83\xb3\xe3\x82\xb9\0" /* offset 9382 */
+  "\xe3\x83\x98\xe3\x82\x9a\xe3\x83\xbc\xe3\x82\xb7\xe3\x82\x99\0" /* offset 9395 */
+  "\xe3\x83\x98\xe3\x82\x99\xe3\x83\xbc\xe3\x82\xbf\0" /* offset 9411 */
+  "\xe3\x83\x9b\xe3\x82\x9a\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x88\0" /* offset 9424 */
+  "\xe3\x83\x9b\xe3\x82\x99\xe3\x83\xab\xe3\x83\x88\0" /* offset 9440 */
+  "\xe3\x83\x9b\xe3\x83\xb3\0" /* offset 9453 */
+  "\xe3\x83\x9b\xe3\x82\x9a\xe3\x83\xb3\xe3\x83\x88\xe3\x82\x99\0" /* offset 9460 */
+  "\xe3\x83\x9b\xe3\x83\xbc\xe3\x83\xab\0" /* offset 9476 */
+  "\xe3\x83\x9b\xe3\x83\xbc\xe3\x83\xb3\0" /* offset 9486 */
+  "\xe3\x83\x9e\xe3\x82\xa4\xe3\x82\xaf\xe3\x83\xad\0" /* offset 9496 */
+  "\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xab\0" /* offset 9509 */
+  "\xe3\x83\x9e\xe3\x83\x83\xe3\x83\x8f\0" /* offset 9519 */
+  "\xe3\x83\x9e\xe3\x83\xab\xe3\x82\xaf\0" /* offset 9529 */
+  "\xe3\x83\x9e\xe3\x83\xb3\xe3\x82\xb7\xe3\x83\xa7\xe3\x83\xb3\0" /* offset 9539 */
+  "\xe3\x83\x9f\xe3\x82\xaf\xe3\x83\xad\xe3\x83\xb3\0" /* offset 9555 */
+  "\xe3\x83\x9f\xe3\x83\xaa\0" /* offset 9568 */
+  "\xe3\x83\x9f\xe3\x83\xaa\xe3\x83\x8f\xe3\x82\x99\xe3\x83\xbc\xe3\x83\xab\0" /* offset 9575 */
+  "\xe3\x83\xa1\xe3\x82\xab\xe3\x82\x99\0" /* offset 9594 */
+  "\xe3\x83\xa1\xe3\x82\xab\xe3\x82\x99\xe3\x83\x88\xe3\x83\xb3\0" /* offset 9604 */
+  "\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88\xe3\x83\xab\0" /* offset 9620 */
+  "\xe3\x83\xa4\xe3\x83\xbc\xe3\x83\x88\xe3\x82\x99\0" /* offset 9633 */
+  "\xe3\x83\xa4\xe3\x83\xbc\xe3\x83\xab\0" /* offset 9646 */
+  "\xe3\x83\xa6\xe3\x82\xa2\xe3\x83\xb3\0" /* offset 9656 */
+  "\xe3\x83\xaa\xe3\x83\x83\xe3\x83\x88\xe3\x83\xab\0" /* offset 9666 */
+  "\xe3\x83\xaa\xe3\x83\xa9\0" /* offset 9679 */
+  "\xe3\x83\xab\xe3\x83\x92\xe3\x82\x9a\xe3\x83\xbc\0" /* offset 9686 */
+  "\xe3\x83\xab\xe3\x83\xbc\xe3\x83\x95\xe3\x82\x99\xe3\x83\xab\0" /* offset 9699 */
+  "\xe3\x83\xac\xe3\x83\xa0\0" /* offset 9715 */
+  "\xe3\x83\xac\xe3\x83\xb3\xe3\x83\x88\xe3\x82\xb1\xe3\x82\x99\xe3\x83\xb3\0" /* offset 9722 */
+  "\xe3\x83\xaf\xe3\x83\x83\xe3\x83\x88\0" /* offset 9741 */
+  "\x30\xe7\x82\xb9\0" /* offset 9751 */
+  "\x31\xe7\x82\xb9\0" /* offset 9756 */
+  "\x32\xe7\x82\xb9\0" /* offset 9761 */
+  "\x33\xe7\x82\xb9\0" /* offset 9766 */
+  "\x34\xe7\x82\xb9\0" /* offset 9771 */
+  "\x35\xe7\x82\xb9\0" /* offset 9776 */
+  "\x36\xe7\x82\xb9\0" /* offset 9781 */
+  "\x37\xe7\x82\xb9\0" /* offset 9786 */
+  "\x38\xe7\x82\xb9\0" /* offset 9791 */
+  "\x39\xe7\x82\xb9\0" /* offset 9796 */
+  "\x31\x30\xe7\x82\xb9\0" /* offset 9801 */
+  "\x31\x31\xe7\x82\xb9\0" /* offset 9807 */
+  "\x31\x32\xe7\x82\xb9\0" /* offset 9813 */
+  "\x31\x33\xe7\x82\xb9\0" /* offset 9819 */
+  "\x31\x34\xe7\x82\xb9\0" /* offset 9825 */
+  "\x31\x35\xe7\x82\xb9\0" /* offset 9831 */
+  "\x31\x36\xe7\x82\xb9\0" /* offset 9837 */
+  "\x31\x37\xe7\x82\xb9\0" /* offset 9843 */
+  "\x31\x38\xe7\x82\xb9\0" /* offset 9849 */
+  "\x31\x39\xe7\x82\xb9\0" /* offset 9855 */
+  "\x32\x30\xe7\x82\xb9\0" /* offset 9861 */
+  "\x32\x31\xe7\x82\xb9\0" /* offset 9867 */
+  "\x32\x32\xe7\x82\xb9\0" /* offset 9873 */
+  "\x32\x33\xe7\x82\xb9\0" /* offset 9879 */
+  "\x32\x34\xe7\x82\xb9\0" /* offset 9885 */
+  "\x68\x50\x61\0" /* offset 9891 */
+  "\x64\x61\0" /* offset 9895 */
+  "\x41\x55\0" /* offset 9898 */
+  "\x62\x61\x72\0" /* offset 9901 */
+  "\x6f\x56\0" /* offset 9905 */
+  "\x70\x63\0" /* offset 9908 */
+  "\xe5\xb9\xb3\xe6\x88\x90\0" /* offset 9911 */
+  "\xe6\x98\xad\xe5\x92\x8c\0" /* offset 9918 */
+  "\xe5\xa4\xa7\xe6\xad\xa3\0" /* offset 9925 */
+  "\xe6\x98\x8e\xe6\xb2\xbb\0" /* offset 9932 */
+  "\xe6\xa0\xaa\xe5\xbc\x8f\xe4\xbc\x9a\xe7\xa4\xbe\0" /* offset 9939 */
+  "\x70\x41\0" /* offset 9952 */
+  "\x6e\x41\0" /* offset 9955 */
+  "\xce\xbc\x41\0" /* offset 9958 */
+  "\x6d\x41\0" /* offset 9962 */
+  "\x6b\x41\0" /* offset 9965 */
+  "\x4b\x42\0" /* offset 9968 */
+  "\x4d\x42\0" /* offset 9971 */
+  "\x47\x42\0" /* offset 9974 */
+  "\x63\x61\x6c\0" /* offset 9977 */
+  "\x6b\x63\x61\x6c\0" /* offset 9981 */
+  "\x70\x46\0" /* offset 9986 */
+  "\x6e\x46\0" /* offset 9989 */
+  "\xce\xbc\x46\0" /* offset 9992 */
+  "\xce\xbc\x67\0" /* offset 9996 */
+  "\x6d\x67\0" /* offset 10000 */
+  "\x6b\x67\0" /* offset 10003 */
+  "\x48\x7a\0" /* offset 10006 */
+  "\x6b\x48\x7a\0" /* offset 10009 */
+  "\x4d\x48\x7a\0" /* offset 10013 */
+  "\x47\x48\x7a\0" /* offset 10017 */
+  "\x54\x48\x7a\0" /* offset 10021 */
+  "\xce\xbc\x6c\0" /* offset 10025 */
+  "\x6d\x6c\0" /* offset 10029 */
+  "\x64\x6c\0" /* offset 10032 */
+  "\x6b\x6c\0" /* offset 10035 */
+  "\x66\x6d\0" /* offset 10038 */
+  "\x6e\x6d\0" /* offset 10041 */
+  "\xce\xbc\x6d\0" /* offset 10044 */
+  "\x6d\x6d\0" /* offset 10048 */
+  "\x63\x6d\0" /* offset 10051 */
+  "\x6b\x6d\0" /* offset 10054 */
+  "\x6d\x6d\x32\0" /* offset 10057 */
+  "\x63\x6d\x32\0" /* offset 10061 */
+  "\x6d\x32\0" /* offset 10065 */
+  "\x6b\x6d\x32\0" /* offset 10068 */
+  "\x6d\x6d\x33\0" /* offset 10072 */
+  "\x63\x6d\x33\0" /* offset 10076 */
+  "\x6d\x33\0" /* offset 10080 */
+  "\x6b\x6d\x33\0" /* offset 10083 */
+  "\x6d\xe2\x88\x95\x73\0" /* offset 10087 */
+  "\x6d\xe2\x88\x95\x73\x32\0" /* offset 10093 */
+  "\x50\x61\0" /* offset 10100 */
+  "\x6b\x50\x61\0" /* offset 10103 */
+  "\x4d\x50\x61\0" /* offset 10107 */
+  "\x47\x50\x61\0" /* offset 10111 */
+  "\x72\x61\x64\0" /* offset 10115 */
+  "\x72\x61\x64\xe2\x88\x95\x73\0" /* offset 10119 */
+  "\x72\x61\x64\xe2\x88\x95\x73\x32\0" /* offset 10127 */
+  "\x70\x73\0" /* offset 10136 */
+  "\x6e\x73\0" /* offset 10139 */
+  "\xce\xbc\x73\0" /* offset 10142 */
+  "\x6d\x73\0" /* offset 10146 */
+  "\x70\x56\0" /* offset 10149 */
+  "\x6e\x56\0" /* offset 10152 */
+  "\xce\xbc\x56\0" /* offset 10155 */
+  "\x6d\x56\0" /* offset 10159 */
+  "\x6b\x56\0" /* offset 10162 */
+  "\x4d\x56\0" /* offset 10165 */
+  "\x70\x57\0" /* offset 10168 */
+  "\x6e\x57\0" /* offset 10171 */
+  "\xce\xbc\x57\0" /* offset 10174 */
+  "\x6d\x57\0" /* offset 10178 */
+  "\x6b\x57\0" /* offset 10181 */
+  "\x4d\x57\0" /* offset 10184 */
+  "\x6b\xce\xa9\0" /* offset 10187 */
+  "\x4d\xce\xa9\0" /* offset 10191 */
+  "\x61\x2e\x6d\x2e\0" /* offset 10195 */
+  "\x42\x71\0" /* offset 10200 */
+  "\x63\x63\0" /* offset 10203 */
+  "\x63\x64\0" /* offset 10206 */
+  "\x43\xe2\x88\x95\x6b\x67\0" /* offset 10209 */
+  "\x43\x6f\x2e\0" /* offset 10216 */
+  "\x64\x42\0" /* offset 10220 */
+  "\x47\x79\0" /* offset 10223 */
+  "\x68\x61\0" /* offset 10226 */
+  "\x48\x50\0" /* offset 10229 */
+  "\x69\x6e\0" /* offset 10232 */
+  "\x4b\x4b\0" /* offset 10235 */
+  "\x4b\x4d\0" /* offset 10238 */
+  "\x6b\x74\0" /* offset 10241 */
+  "\x6c\x6d\0" /* offset 10244 */
+  "\x6c\x6e\0" /* offset 10247 */
+  "\x6c\x6f\x67\0" /* offset 10250 */
+  "\x6c\x78\0" /* offset 10254 */
+  "\x6d\x62\0" /* offset 10257 */
+  "\x6d\x69\x6c\0" /* offset 10260 */
+  "\x6d\x6f\x6c\0" /* offset 10264 */
+  "\x50\x48\0" /* offset 10268 */
+  "\x70\x2e\x6d\x2e\0" /* offset 10271 */
+  "\x50\x50\x4d\0" /* offset 10276 */
+  "\x50\x52\0" /* offset 10280 */
+  "\x73\x72\0" /* offset 10283 */
+  "\x53\x76\0" /* offset 10286 */
+  "\x57\x62\0" /* offset 10289 */
+  "\x31\xe6\x97\xa5\0" /* offset 10292 */
+  "\x32\xe6\x97\xa5\0" /* offset 10297 */
+  "\x33\xe6\x97\xa5\0" /* offset 10302 */
+  "\x34\xe6\x97\xa5\0" /* offset 10307 */
+  "\x35\xe6\x97\xa5\0" /* offset 10312 */
+  "\x36\xe6\x97\xa5\0" /* offset 10317 */
+  "\x37\xe6\x97\xa5\0" /* offset 10322 */
+  "\x38\xe6\x97\xa5\0" /* offset 10327 */
+  "\x39\xe6\x97\xa5\0" /* offset 10332 */
+  "\x31\x30\xe6\x97\xa5\0" /* offset 10337 */
+  "\x31\x31\xe6\x97\xa5\0" /* offset 10343 */
+  "\x31\x32\xe6\x97\xa5\0" /* offset 10349 */
+  "\x31\x33\xe6\x97\xa5\0" /* offset 10355 */
+  "\x31\x34\xe6\x97\xa5\0" /* offset 10361 */
+  "\x31\x35\xe6\x97\xa5\0" /* offset 10367 */
+  "\x31\x36\xe6\x97\xa5\0" /* offset 10373 */
+  "\x31\x37\xe6\x97\xa5\0" /* offset 10379 */
+  "\x31\x38\xe6\x97\xa5\0" /* offset 10385 */
+  "\x31\x39\xe6\x97\xa5\0" /* offset 10391 */
+  "\x32\x30\xe6\x97\xa5\0" /* offset 10397 */
+  "\x32\x31\xe6\x97\xa5\0" /* offset 10403 */
+  "\x32\x32\xe6\x97\xa5\0" /* offset 10409 */
+  "\x32\x33\xe6\x97\xa5\0" /* offset 10415 */
+  "\x32\x34\xe6\x97\xa5\0" /* offset 10421 */
+  "\x32\x35\xe6\x97\xa5\0" /* offset 10427 */
+  "\x32\x36\xe6\x97\xa5\0" /* offset 10433 */
+  "\x32\x37\xe6\x97\xa5\0" /* offset 10439 */
+  "\x32\x38\xe6\x97\xa5\0" /* offset 10445 */
+  "\x32\x39\xe6\x97\xa5\0" /* offset 10451 */
+  "\x33\x30\xe6\x97\xa5\0" /* offset 10457 */
+  "\x33\x31\xe6\x97\xa5\0" /* offset 10463 */
+  "\xe8\xb1\x88\0" /* offset 10469 */
+  "\xe6\x9b\xb4\0" /* offset 10473 */
+  "\xe8\xb3\x88\0" /* offset 10477 */
+  "\xe6\xbb\x91\0" /* offset 10481 */
+  "\xe4\xb8\xb2\0" /* offset 10485 */
+  "\xe5\x8f\xa5\0" /* offset 10489 */
+  "\xe5\xa5\x91\0" /* offset 10493 */
+  "\xe5\x96\x87\0" /* offset 10497 */
+  "\xe5\xa5\x88\0" /* offset 10501 */
+  "\xe6\x87\xb6\0" /* offset 10505 */
+  "\xe7\x99\xa9\0" /* offset 10509 */
+  "\xe7\xbe\x85\0" /* offset 10513 */
+  "\xe8\x98\xbf\0" /* offset 10517 */
+  "\xe8\x9e\xba\0" /* offset 10521 */
+  "\xe8\xa3\xb8\0" /* offset 10525 */
+  "\xe9\x82\x8f\0" /* offset 10529 */
+  "\xe6\xa8\x82\0" /* offset 10533 */
+  "\xe6\xb4\x9b\0" /* offset 10537 */
+  "\xe7\x83\x99\0" /* offset 10541 */
+  "\xe7\x8f\x9e\0" /* offset 10545 */
+  "\xe8\x90\xbd\0" /* offset 10549 */
+  "\xe9\x85\xaa\0" /* offset 10553 */
+  "\xe9\xa7\xb1\0" /* offset 10557 */
+  "\xe4\xba\x82\0" /* offset 10561 */
+  "\xe5\x8d\xb5\0" /* offset 10565 */
+  "\xe6\xac\x84\0" /* offset 10569 */
+  "\xe7\x88\x9b\0" /* offset 10573 */
+  "\xe8\x98\xad\0" /* offset 10577 */
+  "\xe9\xb8\x9e\0" /* offset 10581 */
+  "\xe5\xb5\x90\0" /* offset 10585 */
+  "\xe6\xbf\xab\0" /* offset 10589 */
+  "\xe8\x97\x8d\0" /* offset 10593 */
+  "\xe8\xa5\xa4\0" /* offset 10597 */
+  "\xe6\x8b\x89\0" /* offset 10601 */
+  "\xe8\x87\x98\0" /* offset 10605 */
+  "\xe8\xa0\x9f\0" /* offset 10609 */
+  "\xe5\xbb\x8a\0" /* offset 10613 */
+  "\xe6\x9c\x97\0" /* offset 10617 */
+  "\xe6\xb5\xaa\0" /* offset 10621 */
+  "\xe7\x8b\xbc\0" /* offset 10625 */
+  "\xe9\x83\x8e\0" /* offset 10629 */
+  "\xe4\xbe\x86\0" /* offset 10633 */
+  "\xe5\x86\xb7\0" /* offset 10637 */
+  "\xe5\x8b\x9e\0" /* offset 10641 */
+  "\xe6\x93\x84\0" /* offset 10645 */
+  "\xe6\xab\x93\0" /* offset 10649 */
+  "\xe7\x88\x90\0" /* offset 10653 */
+  "\xe7\x9b\xa7\0" /* offset 10657 */
+  "\xe8\x98\x86\0" /* offset 10661 */
+  "\xe8\x99\x9c\0" /* offset 10665 */
+  "\xe8\xb7\xaf\0" /* offset 10669 */
+  "\xe9\x9c\xb2\0" /* offset 10673 */
+  "\xe9\xad\xaf\0" /* offset 10677 */
+  "\xe9\xb7\xba\0" /* offset 10681 */
+  "\xe7\xa2\x8c\0" /* offset 10685 */
+  "\xe7\xa5\xbf\0" /* offset 10689 */
+  "\xe7\xb6\xa0\0" /* offset 10693 */
+  "\xe8\x8f\x89\0" /* offset 10697 */
+  "\xe9\x8c\x84\0" /* offset 10701 */
+  "\xe8\xab\x96\0" /* offset 10705 */
+  "\xe5\xa3\x9f\0" /* offset 10709 */
+  "\xe5\xbc\x84\0" /* offset 10713 */
+  "\xe7\xb1\xa0\0" /* offset 10717 */
+  "\xe8\x81\xbe\0" /* offset 10721 */
+  "\xe7\x89\xa2\0" /* offset 10725 */
+  "\xe7\xa3\x8a\0" /* offset 10729 */
+  "\xe8\xb3\x82\0" /* offset 10733 */
+  "\xe9\x9b\xb7\0" /* offset 10737 */
+  "\xe5\xa3\x98\0" /* offset 10741 */
+  "\xe5\xb1\xa2\0" /* offset 10745 */
+  "\xe6\xa8\x93\0" /* offset 10749 */
+  "\xe6\xb7\x9a\0" /* offset 10753 */
+  "\xe6\xbc\x8f\0" /* offset 10757 */
+  "\xe7\xb4\xaf\0" /* offset 10761 */
+  "\xe7\xb8\xb7\0" /* offset 10765 */
+  "\xe9\x99\x8b\0" /* offset 10769 */
+  "\xe5\x8b\x92\0" /* offset 10773 */
+  "\xe8\x82\x8b\0" /* offset 10777 */
+  "\xe5\x87\x9c\0" /* offset 10781 */
+  "\xe5\x87\x8c\0" /* offset 10785 */
+  "\xe7\xa8\x9c\0" /* offset 10789 */
+  "\xe7\xb6\xbe\0" /* offset 10793 */
+  "\xe8\x8f\xb1\0" /* offset 10797 */
+  "\xe9\x99\xb5\0" /* offset 10801 */
+  "\xe8\xae\x80\0" /* offset 10805 */
+  "\xe6\x8b\x8f\0" /* offset 10809 */
+  "\xe8\xab\xbe\0" /* offset 10813 */
+  "\xe4\xb8\xb9\0" /* offset 10817 */
+  "\xe5\xaf\xa7\0" /* offset 10821 */
+  "\xe6\x80\x92\0" /* offset 10825 */
+  "\xe7\x8e\x87\0" /* offset 10829 */
+  "\xe7\x95\xb0\0" /* offset 10833 */
+  "\xe5\x8c\x97\0" /* offset 10837 */
+  "\xe7\xa3\xbb\0" /* offset 10841 */
+  "\xe4\xbe\xbf\0" /* offset 10845 */
+  "\xe5\xbe\xa9\0" /* offset 10849 */
+  "\xe4\xb8\x8d\0" /* offset 10853 */
+  "\xe6\xb3\x8c\0" /* offset 10857 */
+  "\xe6\x95\xb8\0" /* offset 10861 */
+  "\xe7\xb4\xa2\0" /* offset 10865 */
+  "\xe5\x8f\x83\0" /* offset 10869 */
+  "\xe5\xa1\x9e\0" /* offset 10873 */
+  "\xe7\x9c\x81\0" /* offset 10877 */
+  "\xe8\x91\x89\0" /* offset 10881 */
+  "\xe8\xaa\xaa\0" /* offset 10885 */
+  "\xe6\xae\xba\0" /* offset 10889 */
+  "\xe6\xb2\x88\0" /* offset 10893 */
+  "\xe6\x8b\xbe\0" /* offset 10897 */
+  "\xe8\x8b\xa5\0" /* offset 10901 */
+  "\xe6\x8e\xa0\0" /* offset 10905 */
+  "\xe7\x95\xa5\0" /* offset 10909 */
+  "\xe4\xba\xae\0" /* offset 10913 */
+  "\xe5\x85\xa9\0" /* offset 10917 */
+  "\xe5\x87\x89\0" /* offset 10921 */
+  "\xe6\xa2\x81\0" /* offset 10925 */
+  "\xe7\xb3\xa7\0" /* offset 10929 */
+  "\xe8\x89\xaf\0" /* offset 10933 */
+  "\xe8\xab\x92\0" /* offset 10937 */
+  "\xe9\x87\x8f\0" /* offset 10941 */
+  "\xe5\x8b\xb5\0" /* offset 10945 */
+  "\xe5\x91\x82\0" /* offset 10949 */
+  "\xe5\xbb\xac\0" /* offset 10953 */
+  "\xe6\x97\x85\0" /* offset 10957 */
+  "\xe6\xbf\xbe\0" /* offset 10961 */
+  "\xe7\xa4\xaa\0" /* offset 10965 */
+  "\xe9\x96\xad\0" /* offset 10969 */
+  "\xe9\xa9\xaa\0" /* offset 10973 */
+  "\xe9\xba\x97\0" /* offset 10977 */
+  "\xe9\xbb\x8e\0" /* offset 10981 */
+  "\xe6\x9b\x86\0" /* offset 10985 */
+  "\xe6\xad\xb7\0" /* offset 10989 */
+  "\xe8\xbd\xa2\0" /* offset 10993 */
+  "\xe5\xb9\xb4\0" /* offset 10997 */
+  "\xe6\x86\x90\0" /* offset 11001 */
+  "\xe6\x88\x80\0" /* offset 11005 */
+  "\xe6\x92\x9a\0" /* offset 11009 */
+  "\xe6\xbc\xa3\0" /* offset 11013 */
+  "\xe7\x85\x89\0" /* offset 11017 */
+  "\xe7\x92\x89\0" /* offset 11021 */
+  "\xe7\xa7\x8a\0" /* offset 11025 */
+  "\xe7\xb7\xb4\0" /* offset 11029 */
+  "\xe8\x81\xaf\0" /* offset 11033 */
+  "\xe8\xbc\xa6\0" /* offset 11037 */
+  "\xe8\x93\xae\0" /* offset 11041 */
+  "\xe9\x80\xa3\0" /* offset 11045 */
+  "\xe9\x8d\x8a\0" /* offset 11049 */
+  "\xe5\x88\x97\0" /* offset 11053 */
+  "\xe5\x8a\xa3\0" /* offset 11057 */
+  "\xe5\x92\xbd\0" /* offset 11061 */
+  "\xe7\x83\x88\0" /* offset 11065 */
+  "\xe8\xa3\x82\0" /* offset 11069 */
+  "\xe5\xbb\x89\0" /* offset 11073 */
+  "\xe5\xbf\xb5\0" /* offset 11077 */
+  "\xe6\x8d\xbb\0" /* offset 11081 */
+  "\xe6\xae\xae\0" /* offset 11085 */
+  "\xe7\xb0\xbe\0" /* offset 11089 */
+  "\xe7\x8d\xb5\0" /* offset 11093 */
+  "\xe4\xbb\xa4\0" /* offset 11097 */
+  "\xe5\x9b\xb9\0" /* offset 11101 */
+  "\xe5\xb6\xba\0" /* offset 11105 */
+  "\xe6\x80\x9c\0" /* offset 11109 */
+  "\xe7\x8e\xb2\0" /* offset 11113 */
+  "\xe7\x91\xa9\0" /* offset 11117 */
+  "\xe7\xbe\x9a\0" /* offset 11121 */
+  "\xe8\x81\x86\0" /* offset 11125 */
+  "\xe9\x88\xb4\0" /* offset 11129 */
+  "\xe9\x9b\xb6\0" /* offset 11133 */
+  "\xe9\x9d\x88\0" /* offset 11137 */
+  "\xe9\xa0\x98\0" /* offset 11141 */
+  "\xe4\xbe\x8b\0" /* offset 11145 */
+  "\xe7\xa6\xae\0" /* offset 11149 */
+  "\xe9\x86\xb4\0" /* offset 11153 */
+  "\xe9\x9a\xb8\0" /* offset 11157 */
+  "\xe6\x83\xa1\0" /* offset 11161 */
+  "\xe4\xba\x86\0" /* offset 11165 */
+  "\xe5\x83\x9a\0" /* offset 11169 */
+  "\xe5\xaf\xae\0" /* offset 11173 */
+  "\xe5\xb0\xbf\0" /* offset 11177 */
+  "\xe6\x96\x99\0" /* offset 11181 */
+  "\xe7\x87\x8e\0" /* offset 11185 */
+  "\xe7\x99\x82\0" /* offset 11189 */
+  "\xe8\x93\xbc\0" /* offset 11193 */
+  "\xe9\x81\xbc\0" /* offset 11197 */
+  "\xe6\x9a\x88\0" /* offset 11201 */
+  "\xe9\x98\xae\0" /* offset 11205 */
+  "\xe5\x8a\x89\0" /* offset 11209 */
+  "\xe6\x9d\xbb\0" /* offset 11213 */
+  "\xe6\x9f\xb3\0" /* offset 11217 */
+  "\xe6\xb5\x81\0" /* offset 11221 */
+  "\xe6\xba\x9c\0" /* offset 11225 */
+  "\xe7\x90\x89\0" /* offset 11229 */
+  "\xe7\x95\x99\0" /* offset 11233 */
+  "\xe7\xa1\xab\0" /* offset 11237 */
+  "\xe7\xb4\x90\0" /* offset 11241 */
+  "\xe9\xa1\x9e\0" /* offset 11245 */
+  "\xe6\x88\xae\0" /* offset 11249 */
+  "\xe9\x99\xb8\0" /* offset 11253 */
+  "\xe5\x80\xab\0" /* offset 11257 */
+  "\xe5\xb4\x99\0" /* offset 11261 */
+  "\xe6\xb7\xaa\0" /* offset 11265 */
+  "\xe8\xbc\xaa\0" /* offset 11269 */
+  "\xe5\xbe\x8b\0" /* offset 11273 */
+  "\xe6\x85\x84\0" /* offset 11277 */
+  "\xe6\xa0\x97\0" /* offset 11281 */
+  "\xe9\x9a\x86\0" /* offset 11285 */
+  "\xe5\x88\xa9\0" /* offset 11289 */
+  "\xe5\x90\x8f\0" /* offset 11293 */
+  "\xe5\xb1\xa5\0" /* offset 11297 */
+  "\xe6\x98\x93\0" /* offset 11301 */
+  "\xe6\x9d\x8e\0" /* offset 11305 */
+  "\xe6\xa2\xa8\0" /* offset 11309 */
+  "\xe6\xb3\xa5\0" /* offset 11313 */
+  "\xe7\x90\x86\0" /* offset 11317 */
+  "\xe7\x97\xa2\0" /* offset 11321 */
+  "\xe7\xbd\xb9\0" /* offset 11325 */
+  "\xe8\xa3\x8f\0" /* offset 11329 */
+  "\xe8\xa3\xa1\0" /* offset 11333 */
+  "\xe9\x9b\xa2\0" /* offset 11337 */
+  "\xe5\x8c\xbf\0" /* offset 11341 */
+  "\xe6\xba\xba\0" /* offset 11345 */
+  "\xe5\x90\x9d\0" /* offset 11349 */
+  "\xe7\x87\x90\0" /* offset 11353 */
+  "\xe7\x92\x98\0" /* offset 11357 */
+  "\xe8\x97\xba\0" /* offset 11361 */
+  "\xe9\x9a\xa3\0" /* offset 11365 */
+  "\xe9\xb1\x97\0" /* offset 11369 */
+  "\xe9\xba\x9f\0" /* offset 11373 */
+  "\xe6\x9e\x97\0" /* offset 11377 */
+  "\xe6\xb7\x8b\0" /* offset 11381 */
+  "\xe8\x87\xa8\0" /* offset 11385 */
+  "\xe7\xac\xa0\0" /* offset 11389 */
+  "\xe7\xb2\x92\0" /* offset 11393 */
+  "\xe7\x8b\x80\0" /* offset 11397 */
+  "\xe7\x82\x99\0" /* offset 11401 */
+  "\xe8\xad\x98\0" /* offset 11405 */
+  "\xe4\xbb\x80\0" /* offset 11409 */
+  "\xe8\x8c\xb6\0" /* offset 11413 */
+  "\xe5\x88\xba\0" /* offset 11417 */
+  "\xe5\x88\x87\0" /* offset 11421 */
+  "\xe5\xba\xa6\0" /* offset 11425 */
+  "\xe6\x8b\x93\0" /* offset 11429 */
+  "\xe7\xb3\x96\0" /* offset 11433 */
+  "\xe5\xae\x85\0" /* offset 11437 */
+  "\xe6\xb4\x9e\0" /* offset 11441 */
+  "\xe6\x9a\xb4\0" /* offset 11445 */
+  "\xe8\xbc\xbb\0" /* offset 11449 */
+  "\xe9\x99\x8d\0" /* offset 11453 */
+  "\xe5\xbb\x93\0" /* offset 11457 */
+  "\xe5\x85\x80\0" /* offset 11461 */
+  "\xe5\x97\x80\0" /* offset 11465 */
+  "\xe5\xa1\x9a\0" /* offset 11469 */
+  "\xe6\x99\xb4\0" /* offset 11473 */
+  "\xe5\x87\x9e\0" /* offset 11477 */
+  "\xe7\x8c\xaa\0" /* offset 11481 */
+  "\xe7\x9b\x8a\0" /* offset 11485 */
+  "\xe7\xa4\xbc\0" /* offset 11489 */
+  "\xe7\xa5\x9e\0" /* offset 11493 */
+  "\xe7\xa5\xa5\0" /* offset 11497 */
+  "\xe7\xa6\x8f\0" /* offset 11501 */
+  "\xe9\x9d\x96\0" /* offset 11505 */
+  "\xe7\xb2\xbe\0" /* offset 11509 */
+  "\xe8\x98\x92\0" /* offset 11513 */
+  "\xe8\xab\xb8\0" /* offset 11517 */
+  "\xe9\x80\xb8\0" /* offset 11521 */
+  "\xe9\x83\xbd\0" /* offset 11525 */
+  "\xe9\xa3\xaf\0" /* offset 11529 */
+  "\xe9\xa3\xbc\0" /* offset 11533 */
+  "\xe9\xa4\xa8\0" /* offset 11537 */
+  "\xe9\xb6\xb4\0" /* offset 11541 */
+  "\xe4\xbe\xae\0" /* offset 11545 */
+  "\xe5\x83\xa7\0" /* offset 11549 */
+  "\xe5\x85\x8d\0" /* offset 11553 */
+  "\xe5\x8b\x89\0" /* offset 11557 */
+  "\xe5\x8b\xa4\0" /* offset 11561 */
+  "\xe5\x8d\x91\0" /* offset 11565 */
+  "\xe5\x96\x9d\0" /* offset 11569 */
+  "\xe5\x98\x86\0" /* offset 11573 */
+  "\xe5\x99\xa8\0" /* offset 11577 */
+  "\xe5\xa1\x80\0" /* offset 11581 */
+  "\xe5\xa2\xa8\0" /* offset 11585 */
+  "\xe5\xb1\xa4\0" /* offset 11589 */
+  "\xe6\x82\x94\0" /* offset 11593 */
+  "\xe6\x85\xa8\0" /* offset 11597 */
+  "\xe6\x86\x8e\0" /* offset 11601 */
+  "\xe6\x87\xb2\0" /* offset 11605 */
+  "\xe6\x95\x8f\0" /* offset 11609 */
+  "\xe6\x97\xa2\0" /* offset 11613 */
+  "\xe6\x9a\x91\0" /* offset 11617 */
+  "\xe6\xa2\x85\0" /* offset 11621 */
+  "\xe6\xb5\xb7\0" /* offset 11625 */
+  "\xe6\xb8\x9a\0" /* offset 11629 */
+  "\xe6\xbc\xa2\0" /* offset 11633 */
+  "\xe7\x85\xae\0" /* offset 11637 */
+  "\xe7\x88\xab\0" /* offset 11641 */
+  "\xe7\x90\xa2\0" /* offset 11645 */
+  "\xe7\xa2\x91\0" /* offset 11649 */
+  "\xe7\xa5\x89\0" /* offset 11653 */
+  "\xe7\xa5\x88\0" /* offset 11657 */
+  "\xe7\xa5\x90\0" /* offset 11661 */
+  "\xe7\xa5\x96\0" /* offset 11665 */
+  "\xe7\xa6\x8d\0" /* offset 11669 */
+  "\xe7\xa6\x8e\0" /* offset 11673 */
+  "\xe7\xa9\x80\0" /* offset 11677 */
+  "\xe7\xaa\x81\0" /* offset 11681 */
+  "\xe7\xaf\x80\0" /* offset 11685 */
+  "\xe7\xb8\x89\0" /* offset 11689 */
+  "\xe7\xb9\x81\0" /* offset 11693 */
+  "\xe7\xbd\xb2\0" /* offset 11697 */
+  "\xe8\x80\x85\0" /* offset 11701 */
+  "\xe8\x87\xad\0" /* offset 11705 */
+  "\xe8\x89\xb9\0" /* offset 11709 */
+  "\xe8\x91\x97\0" /* offset 11713 */
+  "\xe8\xa4\x90\0" /* offset 11717 */
+  "\xe8\xa6\x96\0" /* offset 11721 */
+  "\xe8\xac\x81\0" /* offset 11725 */
+  "\xe8\xac\xb9\0" /* offset 11729 */
+  "\xe8\xb3\x93\0" /* offset 11733 */
+  "\xe8\xb4\x88\0" /* offset 11737 */
+  "\xe8\xbe\xb6\0" /* offset 11741 */
+  "\xe9\x9b\xa3\0" /* offset 11745 */
+  "\xe9\x9f\xbf\0" /* offset 11749 */
+  "\xe9\xa0\xbb\0" /* offset 11753 */
+  "\x66\x66\0" /* offset 11757 */
+  "\x66\x69\0" /* offset 11760 */
+  "\x66\x6c\0" /* offset 11763 */
+  "\x66\x66\x69\0" /* offset 11766 */
+  "\x66\x66\x6c\0" /* offset 11770 */
+  "\x73\x74\0" /* offset 11774 */
+  "\xd5\xb4\xd5\xb6\0" /* offset 11777 */
+  "\xd5\xb4\xd5\xa5\0" /* offset 11782 */
+  "\xd5\xb4\xd5\xab\0" /* offset 11787 */
+  "\xd5\xbe\xd5\xb6\0" /* offset 11792 */
+  "\xd5\xb4\xd5\xad\0" /* offset 11797 */
+  "\xd7\x99\xd6\xb4\0" /* offset 11802 */
+  "\xd7\xb2\xd6\xb7\0" /* offset 11807 */
+  "\xd7\xa2\0" /* offset 11812 */
+  "\xd7\x94\0" /* offset 11815 */
+  "\xd7\x9b\0" /* offset 11818 */
+  "\xd7\x9c\0" /* offset 11821 */
+  "\xd7\x9d\0" /* offset 11824 */
+  "\xd7\xa8\0" /* offset 11827 */
+  "\xd7\xaa\0" /* offset 11830 */
+  "\xd7\xa9\xd7\x81\0" /* offset 11833 */
+  "\xd7\xa9\xd7\x82\0" /* offset 11838 */
+  "\xd7\xa9\xd6\xbc\xd7\x81\0" /* offset 11843 */
+  "\xd7\xa9\xd6\xbc\xd7\x82\0" /* offset 11850 */
+  "\xd7\x90\xd6\xb7\0" /* offset 11857 */
+  "\xd7\x90\xd6\xb8\0" /* offset 11862 */
+  "\xd7\x90\xd6\xbc\0" /* offset 11867 */
+  "\xd7\x91\xd6\xbc\0" /* offset 11872 */
+  "\xd7\x92\xd6\xbc\0" /* offset 11877 */
+  "\xd7\x93\xd6\xbc\0" /* offset 11882 */
+  "\xd7\x94\xd6\xbc\0" /* offset 11887 */
+  "\xd7\x95\xd6\xbc\0" /* offset 11892 */
+  "\xd7\x96\xd6\xbc\0" /* offset 11897 */
+  "\xd7\x98\xd6\xbc\0" /* offset 11902 */
+  "\xd7\x99\xd6\xbc\0" /* offset 11907 */
+  "\xd7\x9a\xd6\xbc\0" /* offset 11912 */
+  "\xd7\x9b\xd6\xbc\0" /* offset 11917 */
+  "\xd7\x9c\xd6\xbc\0" /* offset 11922 */
+  "\xd7\x9e\xd6\xbc\0" /* offset 11927 */
+  "\xd7\xa0\xd6\xbc\0" /* offset 11932 */
+  "\xd7\xa1\xd6\xbc\0" /* offset 11937 */
+  "\xd7\xa3\xd6\xbc\0" /* offset 11942 */
+  "\xd7\xa4\xd6\xbc\0" /* offset 11947 */
+  "\xd7\xa6\xd6\xbc\0" /* offset 11952 */
+  "\xd7\xa7\xd6\xbc\0" /* offset 11957 */
+  "\xd7\xa8\xd6\xbc\0" /* offset 11962 */
+  "\xd7\xa9\xd6\xbc\0" /* offset 11967 */
+  "\xd7\xaa\xd6\xbc\0" /* offset 11972 */
+  "\xd7\x95\xd6\xb9\0" /* offset 11977 */
+  "\xd7\x91\xd6\xbf\0" /* offset 11982 */
+  "\xd7\x9b\xd6\xbf\0" /* offset 11987 */
+  "\xd7\xa4\xd6\xbf\0" /* offset 11992 */
+  "\xd7\x90\xd7\x9c\0" /* offset 11997 */
+  "\xd9\xb1\0" /* offset 12002 */
+  "\xd9\xbb\0" /* offset 12005 */
+  "\xd9\xbe\0" /* offset 12008 */
+  "\xda\x80\0" /* offset 12011 */
+  "\xd9\xba\0" /* offset 12014 */
+  "\xd9\xbf\0" /* offset 12017 */
+  "\xd9\xb9\0" /* offset 12020 */
+  "\xda\xa4\0" /* offset 12023 */
+  "\xda\xa6\0" /* offset 12026 */
+  "\xda\x84\0" /* offset 12029 */
+  "\xda\x83\0" /* offset 12032 */
+  "\xda\x86\0" /* offset 12035 */
+  "\xda\x87\0" /* offset 12038 */
+  "\xda\x8d\0" /* offset 12041 */
+  "\xda\x8c\0" /* offset 12044 */
+  "\xda\x8e\0" /* offset 12047 */
+  "\xda\x88\0" /* offset 12050 */
+  "\xda\x98\0" /* offset 12053 */
+  "\xda\x91\0" /* offset 12056 */
+  "\xda\xa9\0" /* offset 12059 */
+  "\xda\xaf\0" /* offset 12062 */
+  "\xda\xb3\0" /* offset 12065 */
+  "\xda\xb1\0" /* offset 12068 */
+  "\xda\xba\0" /* offset 12071 */
+  "\xda\xbb\0" /* offset 12074 */
+  "\xdb\x81\0" /* offset 12077 */
+  "\xda\xbe\0" /* offset 12080 */
+  "\xdb\x92\0" /* offset 12083 */
+  "\xda\xad\0" /* offset 12086 */
+  "\xdb\x87\0" /* offset 12089 */
+  "\xdb\x86\0" /* offset 12092 */
+  "\xdb\x88\0" /* offset 12095 */
+  "\xdb\x8b\0" /* offset 12098 */
+  "\xdb\x85\0" /* offset 12101 */
+  "\xdb\x89\0" /* offset 12104 */
+  "\xdb\x90\0" /* offset 12107 */
+  "\xd9\x89\0" /* offset 12110 */
+  "\xd9\x8a\xd9\x94\xd8\xa7\0" /* offset 12113 */
+  "\xd9\x8a\xd9\x94\xdb\x95\0" /* offset 12120 */
+  "\xd9\x8a\xd9\x94\xd9\x88\0" /* offset 12127 */
+  "\xd9\x8a\xd9\x94\xdb\x87\0" /* offset 12134 */
+  "\xd9\x8a\xd9\x94\xdb\x86\0" /* offset 12141 */
+  "\xd9\x8a\xd9\x94\xdb\x88\0" /* offset 12148 */
+  "\xd9\x8a\xd9\x94\xdb\x90\0" /* offset 12155 */
+  "\xd9\x8a\xd9\x94\xd9\x89\0" /* offset 12162 */
+  "\xdb\x8c\0" /* offset 12169 */
+  "\xd9\x8a\xd9\x94\xd8\xac\0" /* offset 12172 */
+  "\xd9\x8a\xd9\x94\xd8\xad\0" /* offset 12179 */
+  "\xd9\x8a\xd9\x94\xd9\x85\0" /* offset 12186 */
+  "\xd9\x8a\xd9\x94\xd9\x8a\0" /* offset 12193 */
+  "\xd8\xa8\xd8\xac\0" /* offset 12200 */
+  "\xd8\xa8\xd8\xad\0" /* offset 12205 */
+  "\xd8\xa8\xd8\xae\0" /* offset 12210 */
+  "\xd8\xa8\xd9\x85\0" /* offset 12215 */
+  "\xd8\xa8\xd9\x89\0" /* offset 12220 */
+  "\xd8\xa8\xd9\x8a\0" /* offset 12225 */
+  "\xd8\xaa\xd8\xac\0" /* offset 12230 */
+  "\xd8\xaa\xd8\xad\0" /* offset 12235 */
+  "\xd8\xaa\xd8\xae\0" /* offset 12240 */
+  "\xd8\xaa\xd9\x85\0" /* offset 12245 */
+  "\xd8\xaa\xd9\x89\0" /* offset 12250 */
+  "\xd8\xaa\xd9\x8a\0" /* offset 12255 */
+  "\xd8\xab\xd8\xac\0" /* offset 12260 */
+  "\xd8\xab\xd9\x85\0" /* offset 12265 */
+  "\xd8\xab\xd9\x89\0" /* offset 12270 */
+  "\xd8\xab\xd9\x8a\0" /* offset 12275 */
+  "\xd8\xac\xd8\xad\0" /* offset 12280 */
+  "\xd8\xac\xd9\x85\0" /* offset 12285 */
+  "\xd8\xad\xd8\xac\0" /* offset 12290 */
+  "\xd8\xad\xd9\x85\0" /* offset 12295 */
+  "\xd8\xae\xd8\xac\0" /* offset 12300 */
+  "\xd8\xae\xd8\xad\0" /* offset 12305 */
+  "\xd8\xae\xd9\x85\0" /* offset 12310 */
+  "\xd8\xb3\xd8\xac\0" /* offset 12315 */
+  "\xd8\xb3\xd8\xad\0" /* offset 12320 */
+  "\xd8\xb3\xd8\xae\0" /* offset 12325 */
+  "\xd8\xb3\xd9\x85\0" /* offset 12330 */
+  "\xd8\xb5\xd8\xad\0" /* offset 12335 */
+  "\xd8\xb5\xd9\x85\0" /* offset 12340 */
+  "\xd8\xb6\xd8\xac\0" /* offset 12345 */
+  "\xd8\xb6\xd8\xad\0" /* offset 12350 */
+  "\xd8\xb6\xd8\xae\0" /* offset 12355 */
+  "\xd8\xb6\xd9\x85\0" /* offset 12360 */
+  "\xd8\xb7\xd8\xad\0" /* offset 12365 */
+  "\xd8\xb7\xd9\x85\0" /* offset 12370 */
+  "\xd8\xb8\xd9\x85\0" /* offset 12375 */
+  "\xd8\xb9\xd8\xac\0" /* offset 12380 */
+  "\xd8\xb9\xd9\x85\0" /* offset 12385 */
+  "\xd8\xba\xd8\xac\0" /* offset 12390 */
+  "\xd8\xba\xd9\x85\0" /* offset 12395 */
+  "\xd9\x81\xd8\xac\0" /* offset 12400 */
+  "\xd9\x81\xd8\xad\0" /* offset 12405 */
+  "\xd9\x81\xd8\xae\0" /* offset 12410 */
+  "\xd9\x81\xd9\x85\0" /* offset 12415 */
+  "\xd9\x81\xd9\x89\0" /* offset 12420 */
+  "\xd9\x81\xd9\x8a\0" /* offset 12425 */
+  "\xd9\x82\xd8\xad\0" /* offset 12430 */
+  "\xd9\x82\xd9\x85\0" /* offset 12435 */
+  "\xd9\x82\xd9\x89\0" /* offset 12440 */
+  "\xd9\x82\xd9\x8a\0" /* offset 12445 */
+  "\xd9\x83\xd8\xa7\0" /* offset 12450 */
+  "\xd9\x83\xd8\xac\0" /* offset 12455 */
+  "\xd9\x83\xd8\xad\0" /* offset 12460 */
+  "\xd9\x83\xd8\xae\0" /* offset 12465 */
+  "\xd9\x83\xd9\x84\0" /* offset 12470 */
+  "\xd9\x83\xd9\x85\0" /* offset 12475 */
+  "\xd9\x83\xd9\x89\0" /* offset 12480 */
+  "\xd9\x83\xd9\x8a\0" /* offset 12485 */
+  "\xd9\x84\xd8\xac\0" /* offset 12490 */
+  "\xd9\x84\xd8\xad\0" /* offset 12495 */
+  "\xd9\x84\xd8\xae\0" /* offset 12500 */
+  "\xd9\x84\xd9\x85\0" /* offset 12505 */
+  "\xd9\x84\xd9\x89\0" /* offset 12510 */
+  "\xd9\x84\xd9\x8a\0" /* offset 12515 */
+  "\xd9\x85\xd8\xac\0" /* offset 12520 */
+  "\xd9\x85\xd8\xad\0" /* offset 12525 */
+  "\xd9\x85\xd8\xae\0" /* offset 12530 */
+  "\xd9\x85\xd9\x85\0" /* offset 12535 */
+  "\xd9\x85\xd9\x89\0" /* offset 12540 */
+  "\xd9\x85\xd9\x8a\0" /* offset 12545 */
+  "\xd9\x86\xd8\xac\0" /* offset 12550 */
+  "\xd9\x86\xd8\xad\0" /* offset 12555 */
+  "\xd9\x86\xd8\xae\0" /* offset 12560 */
+  "\xd9\x86\xd9\x85\0" /* offset 12565 */
+  "\xd9\x86\xd9\x89\0" /* offset 12570 */
+  "\xd9\x86\xd9\x8a\0" /* offset 12575 */
+  "\xd9\x87\xd8\xac\0" /* offset 12580 */
+  "\xd9\x87\xd9\x85\0" /* offset 12585 */
+  "\xd9\x87\xd9\x89\0" /* offset 12590 */
+  "\xd9\x87\xd9\x8a\0" /* offset 12595 */
+  "\xd9\x8a\xd8\xac\0" /* offset 12600 */
+  "\xd9\x8a\xd8\xad\0" /* offset 12605 */
+  "\xd9\x8a\xd8\xae\0" /* offset 12610 */
+  "\xd9\x8a\xd9\x85\0" /* offset 12615 */
+  "\xd9\x8a\xd9\x89\0" /* offset 12620 */
+  "\xd9\x8a\xd9\x8a\0" /* offset 12625 */
+  "\xd8\xb0\xd9\xb0\0" /* offset 12630 */
+  "\xd8\xb1\xd9\xb0\0" /* offset 12635 */
+  "\xd9\x89\xd9\xb0\0" /* offset 12640 */
+  "\x20\xd9\x8c\xd9\x91\0" /* offset 12645 */
+  "\x20\xd9\x8d\xd9\x91\0" /* offset 12651 */
+  "\x20\xd9\x8e\xd9\x91\0" /* offset 12657 */
+  "\x20\xd9\x8f\xd9\x91\0" /* offset 12663 */
+  "\x20\xd9\x90\xd9\x91\0" /* offset 12669 */
+  "\x20\xd9\x91\xd9\xb0\0" /* offset 12675 */
+  "\xd9\x8a\xd9\x94\xd8\xb1\0" /* offset 12681 */
+  "\xd9\x8a\xd9\x94\xd8\xb2\0" /* offset 12688 */
+  "\xd9\x8a\xd9\x94\xd9\x86\0" /* offset 12695 */
+  "\xd8\xa8\xd8\xb1\0" /* offset 12702 */
+  "\xd8\xa8\xd8\xb2\0" /* offset 12707 */
+  "\xd8\xa8\xd9\x86\0" /* offset 12712 */
+  "\xd8\xaa\xd8\xb1\0" /* offset 12717 */
+  "\xd8\xaa\xd8\xb2\0" /* offset 12722 */
+  "\xd8\xaa\xd9\x86\0" /* offset 12727 */
+  "\xd8\xab\xd8\xb1\0" /* offset 12732 */
+  "\xd8\xab\xd8\xb2\0" /* offset 12737 */
+  "\xd8\xab\xd9\x86\0" /* offset 12742 */
+  "\xd9\x85\xd8\xa7\0" /* offset 12747 */
+  "\xd9\x86\xd8\xb1\0" /* offset 12752 */
+  "\xd9\x86\xd8\xb2\0" /* offset 12757 */
+  "\xd9\x86\xd9\x86\0" /* offset 12762 */
+  "\xd9\x8a\xd8\xb1\0" /* offset 12767 */
+  "\xd9\x8a\xd8\xb2\0" /* offset 12772 */
+  "\xd9\x8a\xd9\x86\0" /* offset 12777 */
+  "\xd9\x8a\xd9\x94\xd8\xae\0" /* offset 12782 */
+  "\xd9\x8a\xd9\x94\xd9\x87\0" /* offset 12789 */
+  "\xd8\xa8\xd9\x87\0" /* offset 12796 */
+  "\xd8\xaa\xd9\x87\0" /* offset 12801 */
+  "\xd8\xb5\xd8\xae\0" /* offset 12806 */
+  "\xd9\x84\xd9\x87\0" /* offset 12811 */
+  "\xd9\x86\xd9\x87\0" /* offset 12816 */
+  "\xd9\x87\xd9\xb0\0" /* offset 12821 */
+  "\xd9\x8a\xd9\x87\0" /* offset 12826 */
+  "\xd8\xab\xd9\x87\0" /* offset 12831 */
+  "\xd8\xb3\xd9\x87\0" /* offset 12836 */
+  "\xd8\xb4\xd9\x85\0" /* offset 12841 */
+  "\xd8\xb4\xd9\x87\0" /* offset 12846 */
+  "\xd9\x80\xd9\x8e\xd9\x91\0" /* offset 12851 */
+  "\xd9\x80\xd9\x8f\xd9\x91\0" /* offset 12858 */
+  "\xd9\x80\xd9\x90\xd9\x91\0" /* offset 12865 */
+  "\xd8\xb7\xd9\x89\0" /* offset 12872 */
+  "\xd8\xb7\xd9\x8a\0" /* offset 12877 */
+  "\xd8\xb9\xd9\x89\0" /* offset 12882 */
+  "\xd8\xb9\xd9\x8a\0" /* offset 12887 */
+  "\xd8\xba\xd9\x89\0" /* offset 12892 */
+  "\xd8\xba\xd9\x8a\0" /* offset 12897 */
+  "\xd8\xb3\xd9\x89\0" /* offset 12902 */
+  "\xd8\xb3\xd9\x8a\0" /* offset 12907 */
+  "\xd8\xb4\xd9\x89\0" /* offset 12912 */
+  "\xd8\xb4\xd9\x8a\0" /* offset 12917 */
+  "\xd8\xad\xd9\x89\0" /* offset 12922 */
+  "\xd8\xad\xd9\x8a\0" /* offset 12927 */
+  "\xd8\xac\xd9\x89\0" /* offset 12932 */
+  "\xd8\xac\xd9\x8a\0" /* offset 12937 */
+  "\xd8\xae\xd9\x89\0" /* offset 12942 */
+  "\xd8\xae\xd9\x8a\0" /* offset 12947 */
+  "\xd8\xb5\xd9\x89\0" /* offset 12952 */
+  "\xd8\xb5\xd9\x8a\0" /* offset 12957 */
+  "\xd8\xb6\xd9\x89\0" /* offset 12962 */
+  "\xd8\xb6\xd9\x8a\0" /* offset 12967 */
+  "\xd8\xb4\xd8\xac\0" /* offset 12972 */
+  "\xd8\xb4\xd8\xad\0" /* offset 12977 */
+  "\xd8\xb4\xd8\xae\0" /* offset 12982 */
+  "\xd8\xb4\xd8\xb1\0" /* offset 12987 */
+  "\xd8\xb3\xd8\xb1\0" /* offset 12992 */
+  "\xd8\xb5\xd8\xb1\0" /* offset 12997 */
+  "\xd8\xb6\xd8\xb1\0" /* offset 13002 */
+  "\xd8\xa7\xd9\x8b\0" /* offset 13007 */
+  "\xd8\xaa\xd8\xac\xd9\x85\0" /* offset 13012 */
+  "\xd8\xaa\xd8\xad\xd8\xac\0" /* offset 13019 */
+  "\xd8\xaa\xd8\xad\xd9\x85\0" /* offset 13026 */
+  "\xd8\xaa\xd8\xae\xd9\x85\0" /* offset 13033 */
+  "\xd8\xaa\xd9\x85\xd8\xac\0" /* offset 13040 */
+  "\xd8\xaa\xd9\x85\xd8\xad\0" /* offset 13047 */
+  "\xd8\xaa\xd9\x85\xd8\xae\0" /* offset 13054 */
+  "\xd8\xac\xd9\x85\xd8\xad\0" /* offset 13061 */
+  "\xd8\xad\xd9\x85\xd9\x8a\0" /* offset 13068 */
+  "\xd8\xad\xd9\x85\xd9\x89\0" /* offset 13075 */
+  "\xd8\xb3\xd8\xad\xd8\xac\0" /* offset 13082 */
+  "\xd8\xb3\xd8\xac\xd8\xad\0" /* offset 13089 */
+  "\xd8\xb3\xd8\xac\xd9\x89\0" /* offset 13096 */
+  "\xd8\xb3\xd9\x85\xd8\xad\0" /* offset 13103 */
+  "\xd8\xb3\xd9\x85\xd8\xac\0" /* offset 13110 */
+  "\xd8\xb3\xd9\x85\xd9\x85\0" /* offset 13117 */
+  "\xd8\xb5\xd8\xad\xd8\xad\0" /* offset 13124 */
+  "\xd8\xb5\xd9\x85\xd9\x85\0" /* offset 13131 */
+  "\xd8\xb4\xd8\xad\xd9\x85\0" /* offset 13138 */
+  "\xd8\xb4\xd8\xac\xd9\x8a\0" /* offset 13145 */
+  "\xd8\xb4\xd9\x85\xd8\xae\0" /* offset 13152 */
+  "\xd8\xb4\xd9\x85\xd9\x85\0" /* offset 13159 */
+  "\xd8\xb6\xd8\xad\xd9\x89\0" /* offset 13166 */
+  "\xd8\xb6\xd8\xae\xd9\x85\0" /* offset 13173 */
+  "\xd8\xb7\xd9\x85\xd8\xad\0" /* offset 13180 */
+  "\xd8\xb7\xd9\x85\xd9\x85\0" /* offset 13187 */
+  "\xd8\xb7\xd9\x85\xd9\x8a\0" /* offset 13194 */
+  "\xd8\xb9\xd8\xac\xd9\x85\0" /* offset 13201 */
+  "\xd8\xb9\xd9\x85\xd9\x85\0" /* offset 13208 */
+  "\xd8\xb9\xd9\x85\xd9\x89\0" /* offset 13215 */
+  "\xd8\xba\xd9\x85\xd9\x85\0" /* offset 13222 */
+  "\xd8\xba\xd9\x85\xd9\x8a\0" /* offset 13229 */
+  "\xd8\xba\xd9\x85\xd9\x89\0" /* offset 13236 */
+  "\xd9\x81\xd8\xae\xd9\x85\0" /* offset 13243 */
+  "\xd9\x82\xd9\x85\xd8\xad\0" /* offset 13250 */
+  "\xd9\x82\xd9\x85\xd9\x85\0" /* offset 13257 */
+  "\xd9\x84\xd8\xad\xd9\x85\0" /* offset 13264 */
+  "\xd9\x84\xd8\xad\xd9\x8a\0" /* offset 13271 */
+  "\xd9\x84\xd8\xad\xd9\x89\0" /* offset 13278 */
+  "\xd9\x84\xd8\xac\xd8\xac\0" /* offset 13285 */
+  "\xd9\x84\xd8\xae\xd9\x85\0" /* offset 13292 */
+  "\xd9\x84\xd9\x85\xd8\xad\0" /* offset 13299 */
+  "\xd9\x85\xd8\xad\xd8\xac\0" /* offset 13306 */
+  "\xd9\x85\xd8\xad\xd9\x85\0" /* offset 13313 */
+  "\xd9\x85\xd8\xad\xd9\x8a\0" /* offset 13320 */
+  "\xd9\x85\xd8\xac\xd8\xad\0" /* offset 13327 */
+  "\xd9\x85\xd8\xac\xd9\x85\0" /* offset 13334 */
+  "\xd9\x85\xd8\xae\xd8\xac\0" /* offset 13341 */
+  "\xd9\x85\xd8\xae\xd9\x85\0" /* offset 13348 */
+  "\xd9\x85\xd8\xac\xd8\xae\0" /* offset 13355 */
+  "\xd9\x87\xd9\x85\xd8\xac\0" /* offset 13362 */
+  "\xd9\x87\xd9\x85\xd9\x85\0" /* offset 13369 */
+  "\xd9\x86\xd8\xad\xd9\x85\0" /* offset 13376 */
+  "\xd9\x86\xd8\xad\xd9\x89\0" /* offset 13383 */
+  "\xd9\x86\xd8\xac\xd9\x85\0" /* offset 13390 */
+  "\xd9\x86\xd8\xac\xd9\x89\0" /* offset 13397 */
+  "\xd9\x86\xd9\x85\xd9\x8a\0" /* offset 13404 */
+  "\xd9\x86\xd9\x85\xd9\x89\0" /* offset 13411 */
+  "\xd9\x8a\xd9\x85\xd9\x85\0" /* offset 13418 */
+  "\xd8\xa8\xd8\xae\xd9\x8a\0" /* offset 13425 */
+  "\xd8\xaa\xd8\xac\xd9\x8a\0" /* offset 13432 */
+  "\xd8\xaa\xd8\xac\xd9\x89\0" /* offset 13439 */
+  "\xd8\xaa\xd8\xae\xd9\x8a\0" /* offset 13446 */
+  "\xd8\xaa\xd8\xae\xd9\x89\0" /* offset 13453 */
+  "\xd8\xaa\xd9\x85\xd9\x8a\0" /* offset 13460 */
+  "\xd8\xaa\xd9\x85\xd9\x89\0" /* offset 13467 */
+  "\xd8\xac\xd9\x85\xd9\x8a\0" /* offset 13474 */
+  "\xd8\xac\xd8\xad\xd9\x89\0" /* offset 13481 */
+  "\xd8\xac\xd9\x85\xd9\x89\0" /* offset 13488 */
+  "\xd8\xb3\xd8\xae\xd9\x89\0" /* offset 13495 */
+  "\xd8\xb5\xd8\xad\xd9\x8a\0" /* offset 13502 */
+  "\xd8\xb4\xd8\xad\xd9\x8a\0" /* offset 13509 */
+  "\xd8\xb6\xd8\xad\xd9\x8a\0" /* offset 13516 */
+  "\xd9\x84\xd8\xac\xd9\x8a\0" /* offset 13523 */
+  "\xd9\x84\xd9\x85\xd9\x8a\0" /* offset 13530 */
+  "\xd9\x8a\xd8\xad\xd9\x8a\0" /* offset 13537 */
+  "\xd9\x8a\xd8\xac\xd9\x8a\0" /* offset 13544 */
+  "\xd9\x8a\xd9\x85\xd9\x8a\0" /* offset 13551 */
+  "\xd9\x85\xd9\x85\xd9\x8a\0" /* offset 13558 */
+  "\xd9\x82\xd9\x85\xd9\x8a\0" /* offset 13565 */
+  "\xd9\x86\xd8\xad\xd9\x8a\0" /* offset 13572 */
+  "\xd8\xb9\xd9\x85\xd9\x8a\0" /* offset 13579 */
+  "\xd9\x83\xd9\x85\xd9\x8a\0" /* offset 13586 */
+  "\xd9\x86\xd8\xac\xd8\xad\0" /* offset 13593 */
+  "\xd9\x85\xd8\xae\xd9\x8a\0" /* offset 13600 */
+  "\xd9\x84\xd8\xac\xd9\x85\0" /* offset 13607 */
+  "\xd9\x83\xd9\x85\xd9\x85\0" /* offset 13614 */
+  "\xd8\xac\xd8\xad\xd9\x8a\0" /* offset 13621 */
+  "\xd8\xad\xd8\xac\xd9\x8a\0" /* offset 13628 */
+  "\xd9\x85\xd8\xac\xd9\x8a\0" /* offset 13635 */
+  "\xd9\x81\xd9\x85\xd9\x8a\0" /* offset 13642 */
+  "\xd8\xa8\xd8\xad\xd9\x8a\0" /* offset 13649 */
+  "\xd8\xb3\xd8\xae\xd9\x8a\0" /* offset 13656 */
+  "\xd9\x86\xd8\xac\xd9\x8a\0" /* offset 13663 */
+  "\xd8\xb5\xd9\x84\xdb\x92\0" /* offset 13670 */
+  "\xd9\x82\xd9\x84\xdb\x92\0" /* offset 13677 */
+  "\xd8\xa7\xd9\x84\xd9\x84\xd9\x87\0" /* offset 13684 */
+  "\xd8\xa7\xd9\x83\xd8\xa8\xd8\xb1\0" /* offset 13693 */
+  "\xd9\x85\xd8\xad\xd9\x85\xd8\xaf\0" /* offset 13702 */
+  "\xd8\xb5\xd9\x84\xd8\xb9\xd9\x85\0" /* offset 13711 */
+  "\xd8\xb1\xd8\xb3\xd9\x88\xd9\x84\0" /* offset 13720 */
+  "\xd8\xb9\xd9\x84\xd9\x8a\xd9\x87\0" /* offset 13729 */
+  "\xd9\x88\xd8\xb3\xd9\x84\xd9\x85\0" /* offset 13738 */
+  "\xd8\xb5\xd9\x84\xd9\x89\0" /* offset 13747 */
+  "\xd8\xb5\xd9\x84\xd9\x89\x20\xd8\xa7\xd9\x84\xd9\x84\xd9\x87\x20\xd8\xb9\xd9\x84\xd9\x8a\xd9\x87\x20\xd9\x88\xd8\xb3\xd9\x84\xd9\x85\0" /* offset 13754 */
+  "\xd8\xac\xd9\x84\x20\xd8\xac\xd9\x84\xd8\xa7\xd9\x84\xd9\x87\0" /* offset 13788 */
+  "\xd8\xb1\xdb\x8c\xd8\xa7\xd9\x84\0" /* offset 13804 */
+  "\xe2\x80\x94\0" /* offset 13813 */
+  "\xe2\x80\x93\0" /* offset 13817 */
+  "\x5f\0" /* offset 13821 */
+  "\x7b\0" /* offset 13823 */
+  "\x7d\0" /* offset 13825 */
+  "\xe3\x80\x94\0" /* offset 13827 */
+  "\xe3\x80\x95\0" /* offset 13831 */
+  "\xe3\x80\x90\0" /* offset 13835 */
+  "\xe3\x80\x91\0" /* offset 13839 */
+  "\xe3\x80\x8a\0" /* offset 13843 */
+  "\xe3\x80\x8b\0" /* offset 13847 */
+  "\xe3\x80\x8c\0" /* offset 13851 */
+  "\xe3\x80\x8d\0" /* offset 13855 */
+  "\xe3\x80\x8e\0" /* offset 13859 */
+  "\xe3\x80\x8f\0" /* offset 13863 */
+  "\x2c\0" /* offset 13867 */
+  "\xe3\x80\x81\0" /* offset 13869 */
+  "\x3a\0" /* offset 13873 */
+  "\x3f\0" /* offset 13875 */
+  "\x21\0" /* offset 13877 */
+  "\x23\0" /* offset 13879 */
+  "\x26\0" /* offset 13881 */
+  "\x2a\0" /* offset 13883 */
+  "\x2d\0" /* offset 13885 */
+  "\x3c\0" /* offset 13887 */
+  "\x3e\0" /* offset 13889 */
+  "\x5c\0" /* offset 13891 */
+  "\x24\0" /* offset 13893 */
+  "\x25\0" /* offset 13895 */
+  "\x40\0" /* offset 13897 */
+  "\x20\xd9\x8b\0" /* offset 13899 */
+  "\xd9\x80\xd9\x8b\0" /* offset 13903 */
+  "\x20\xd9\x8c\0" /* offset 13908 */
+  "\x20\xd9\x8d\0" /* offset 13912 */
+  "\x20\xd9\x8e\0" /* offset 13916 */
+  "\xd9\x80\xd9\x8e\0" /* offset 13920 */
+  "\x20\xd9\x8f\0" /* offset 13925 */
+  "\xd9\x80\xd9\x8f\0" /* offset 13929 */
+  "\x20\xd9\x90\0" /* offset 13934 */
+  "\xd9\x80\xd9\x90\0" /* offset 13938 */
+  "\x20\xd9\x91\0" /* offset 13943 */
+  "\xd9\x80\xd9\x91\0" /* offset 13947 */
+  "\x20\xd9\x92\0" /* offset 13952 */
+  "\xd9\x80\xd9\x92\0" /* offset 13956 */
+  "\xd8\xa1\0" /* offset 13961 */
+  "\xd8\xa7\0" /* offset 13964 */
+  "\xd8\xa8\0" /* offset 13967 */
+  "\xd8\xa9\0" /* offset 13970 */
+  "\xd8\xaa\0" /* offset 13973 */
+  "\xd8\xab\0" /* offset 13976 */
+  "\xd8\xac\0" /* offset 13979 */
+  "\xd8\xad\0" /* offset 13982 */
+  "\xd8\xae\0" /* offset 13985 */
+  "\xd8\xaf\0" /* offset 13988 */
+  "\xd8\xb0\0" /* offset 13991 */
+  "\xd8\xb1\0" /* offset 13994 */
+  "\xd8\xb2\0" /* offset 13997 */
+  "\xd8\xb3\0" /* offset 14000 */
+  "\xd8\xb4\0" /* offset 14003 */
+  "\xd8\xb5\0" /* offset 14006 */
+  "\xd8\xb6\0" /* offset 14009 */
+  "\xd8\xb7\0" /* offset 14012 */
+  "\xd8\xb8\0" /* offset 14015 */
+  "\xd8\xb9\0" /* offset 14018 */
+  "\xd8\xba\0" /* offset 14021 */
+  "\xd9\x81\0" /* offset 14024 */
+  "\xd9\x82\0" /* offset 14027 */
+  "\xd9\x83\0" /* offset 14030 */
+  "\xd9\x84\0" /* offset 14033 */
+  "\xd9\x85\0" /* offset 14036 */
+  "\xd9\x86\0" /* offset 14039 */
+  "\xd9\x87\0" /* offset 14042 */
+  "\xd9\x88\0" /* offset 14045 */
+  "\xd9\x8a\0" /* offset 14048 */
+  "\xd9\x84\xd8\xa7\xd9\x93\0" /* offset 14051 */
+  "\xd9\x84\xd8\xa7\xd9\x94\0" /* offset 14058 */
+  "\xd9\x84\xd8\xa7\xd9\x95\0" /* offset 14065 */
+  "\xd9\x84\xd8\xa7\0" /* offset 14072 */
+  "\x22\0" /* offset 14077 */
+  "\x27\0" /* offset 14079 */
+  "\x2f\0" /* offset 14081 */
+  "\x5b\0" /* offset 14083 */
+  "\x5d\0" /* offset 14085 */
+  "\x5e\0" /* offset 14087 */
+  "\x7c\0" /* offset 14089 */
+  "\x7e\0" /* offset 14091 */
+  "\xe2\xa6\x85\0" /* offset 14093 */
+  "\xe2\xa6\x86\0" /* offset 14097 */
+  "\xe3\x80\x82\0" /* offset 14101 */
+  "\xe3\x83\xbb\0" /* offset 14105 */
+  "\xe3\x82\xa1\0" /* offset 14109 */
+  "\xe3\x82\xa3\0" /* offset 14113 */
+  "\xe3\x82\xa5\0" /* offset 14117 */
+  "\xe3\x82\xa7\0" /* offset 14121 */
+  "\xe3\x82\xa9\0" /* offset 14125 */
+  "\xe3\x83\xa3\0" /* offset 14129 */
+  "\xe3\x83\xa5\0" /* offset 14133 */
+  "\xe3\x83\xa7\0" /* offset 14137 */
+  "\xe3\x83\x83\0" /* offset 14141 */
+  "\xe3\x83\xbc\0" /* offset 14145 */
+  "\xe3\x83\xb3\0" /* offset 14149 */
+  "\xe3\x82\x99\0" /* offset 14153 */
+  "\xe3\x82\x9a\0" /* offset 14157 */
+  "\xc2\xa2\0" /* offset 14161 */
+  "\xc2\xa3\0" /* offset 14164 */
+  "\xc2\xac\0" /* offset 14167 */
+  "\xc2\xa6\0" /* offset 14170 */
+  "\xc2\xa5\0" /* offset 14173 */
+  "\xe2\x82\xa9\0" /* offset 14176 */
+  "\xe2\x94\x82\0" /* offset 14180 */
+  "\xe2\x86\x90\0" /* offset 14184 */
+  "\xe2\x86\x91\0" /* offset 14188 */
+  "\xe2\x86\x92\0" /* offset 14192 */
+  "\xe2\x86\x93\0" /* offset 14196 */
+  "\xe2\x96\xa0\0" /* offset 14200 */
+  "\xe2\x97\x8b\0" /* offset 14204 */
+  "\xf0\x9d\x85\x97\xf0\x9d\x85\xa5\0" /* offset 14208 */
+  "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\0" /* offset 14217 */
+  "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xae\0" /* offset 14226 */
+  "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xaf\0" /* offset 14239 */
+  "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xb0\0" /* offset 14252 */
+  "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xb1\0" /* offset 14265 */
+  "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xb2\0" /* offset 14278 */
+  "\xf0\x9d\x86\xb9\xf0\x9d\x85\xa5\0" /* offset 14291 */
+  "\xf0\x9d\x86\xba\xf0\x9d\x85\xa5\0" /* offset 14300 */
+  "\xf0\x9d\x86\xb9\xf0\x9d\x85\xa5\xf0\x9d\x85\xae\0" /* offset 14309 */
+  "\xf0\x9d\x86\xba\xf0\x9d\x85\xa5\xf0\x9d\x85\xae\0" /* offset 14322 */
+  "\xf0\x9d\x86\xb9\xf0\x9d\x85\xa5\xf0\x9d\x85\xaf\0" /* offset 14335 */
+  "\xf0\x9d\x86\xba\xf0\x9d\x85\xa5\xf0\x9d\x85\xaf\0" /* offset 14348 */
+  "\xce\x91\0" /* offset 14361 */
+  "\xce\x92\0" /* offset 14364 */
+  "\xce\x94\0" /* offset 14367 */
+  "\xce\x95\0" /* offset 14370 */
+  "\xce\x96\0" /* offset 14373 */
+  "\xce\x97\0" /* offset 14376 */
+  "\xce\x99\0" /* offset 14379 */
+  "\xce\x9a\0" /* offset 14382 */
+  "\xce\x9b\0" /* offset 14385 */
+  "\xce\x9c\0" /* offset 14388 */
+  "\xce\x9d\0" /* offset 14391 */
+  "\xce\x9e\0" /* offset 14394 */
+  "\xce\x9f\0" /* offset 14397 */
+  "\xce\xa1\0" /* offset 14400 */
+  "\xce\xa3\0" /* offset 14403 */
+  "\xce\xa4\0" /* offset 14406 */
+  "\xce\xa6\0" /* offset 14409 */
+  "\xce\xa7\0" /* offset 14412 */
+  "\xce\xa8\0" /* offset 14415 */
+  "\xe2\x88\x87\0" /* offset 14418 */
+  "\xce\xb1\0" /* offset 14422 */
+  "\xce\xb4\0" /* offset 14425 */
+  "\xce\xb6\0" /* offset 14428 */
+  "\xce\xb7\0" /* offset 14431 */
+  "\xce\xbb\0" /* offset 14434 */
+  "\xce\xbd\0" /* offset 14437 */
+  "\xce\xbe\0" /* offset 14440 */
+  "\xce\xbf\0" /* offset 14443 */
+  "\xcf\x83\0" /* offset 14446 */
+  "\xcf\x84\0" /* offset 14449 */
+  "\xcf\x85\0" /* offset 14452 */
+  "\xcf\x87\0" /* offset 14455 */
+  "\xcf\x88\0" /* offset 14458 */
+  "\xcf\x89\0" /* offset 14461 */
+  "\xe2\x88\x82\0" /* offset 14464 */
+  "\xe4\xb8\xbd\0" /* offset 14468 */
+  "\xe4\xb8\xb8\0" /* offset 14472 */
+  "\xe4\xb9\x81\0" /* offset 14476 */
+  "\xf0\xa0\x84\xa2\0" /* offset 14480 */
+  "\xe4\xbd\xa0\0" /* offset 14485 */
+  "\xe4\xbe\xbb\0" /* offset 14489 */
+  "\xe5\x80\x82\0" /* offset 14493 */
+  "\xe5\x81\xba\0" /* offset 14497 */
+  "\xe5\x82\x99\0" /* offset 14501 */
+  "\xe5\x83\x8f\0" /* offset 14505 */
+  "\xe3\x92\x9e\0" /* offset 14509 */
+  "\xf0\xa0\x98\xba\0" /* offset 14513 */
+  "\xe5\x85\x94\0" /* offset 14518 */
+  "\xe5\x85\xa4\0" /* offset 14522 */
+  "\xe5\x85\xb7\0" /* offset 14526 */
+  "\xf0\xa0\x94\x9c\0" /* offset 14530 */
+  "\xe3\x92\xb9\0" /* offset 14535 */
+  "\xe5\x85\xa7\0" /* offset 14539 */
+  "\xe5\x86\x8d\0" /* offset 14543 */
+  "\xf0\xa0\x95\x8b\0" /* offset 14547 */
+  "\xe5\x86\x97\0" /* offset 14552 */
+  "\xe5\x86\xa4\0" /* offset 14556 */
+  "\xe4\xbb\x8c\0" /* offset 14560 */
+  "\xe5\x86\xac\0" /* offset 14564 */
+  "\xe5\x86\xb5\0" /* offset 14568 */
+  "\xf0\xa9\x87\x9f\0" /* offset 14572 */
+  "\xe5\x88\x83\0" /* offset 14577 */
+  "\xe3\x93\x9f\0" /* offset 14581 */
+  "\xe5\x88\xbb\0" /* offset 14585 */
+  "\xe5\x89\x86\0" /* offset 14589 */
+  "\xe5\x89\xb2\0" /* offset 14593 */
+  "\xe5\x89\xb7\0" /* offset 14597 */
+  "\xe3\x94\x95\0" /* offset 14601 */
+  "\xe5\x8b\x87\0" /* offset 14605 */
+  "\xe5\x8b\xba\0" /* offset 14609 */
+  "\xe5\x8c\x85\0" /* offset 14613 */
+  "\xe5\x8c\x86\0" /* offset 14617 */
+  "\xe5\x8d\x89\0" /* offset 14621 */
+  "\xe5\x8d\x9a\0" /* offset 14625 */
+  "\xe5\x8d\xb3\0" /* offset 14629 */
+  "\xe5\x8d\xbd\0" /* offset 14633 */
+  "\xe5\x8d\xbf\0" /* offset 14637 */
+  "\xf0\xa0\xa8\xac\0" /* offset 14641 */
+  "\xe7\x81\xb0\0" /* offset 14646 */
+  "\xe5\x8f\x8a\0" /* offset 14650 */
+  "\xe5\x8f\x9f\0" /* offset 14654 */
+  "\xf0\xa0\xad\xa3\0" /* offset 14658 */
+  "\xe5\x8f\xab\0" /* offset 14663 */
+  "\xe5\x8f\xb1\0" /* offset 14667 */
+  "\xe5\x90\x86\0" /* offset 14671 */
+  "\xe5\x92\x9e\0" /* offset 14675 */
+  "\xe5\x90\xb8\0" /* offset 14679 */
+  "\xe5\x91\x88\0" /* offset 14683 */
+  "\xe5\x91\xa8\0" /* offset 14687 */
+  "\xe5\x92\xa2\0" /* offset 14691 */
+  "\xe5\x93\xb6\0" /* offset 14695 */
+  "\xe5\x94\x90\0" /* offset 14699 */
+  "\xe5\x95\x93\0" /* offset 14703 */
+  "\xe5\x95\xa3\0" /* offset 14707 */
+  "\xe5\x96\x84\0" /* offset 14711 */
+  "\xe5\x96\x99\0" /* offset 14715 */
+  "\xe5\x96\xab\0" /* offset 14719 */
+  "\xe5\x96\xb3\0" /* offset 14723 */
+  "\xe5\x97\x82\0" /* offset 14727 */
+  "\xe5\x9c\x96\0" /* offset 14731 */
+  "\xe5\x9c\x97\0" /* offset 14735 */
+  "\xe5\x99\x91\0" /* offset 14739 */
+  "\xe5\x99\xb4\0" /* offset 14743 */
+  "\xe5\xa3\xae\0" /* offset 14747 */
+  "\xe5\x9f\x8e\0" /* offset 14751 */
+  "\xe5\x9f\xb4\0" /* offset 14755 */
+  "\xe5\xa0\x8d\0" /* offset 14759 */
+  "\xe5\x9e\x8b\0" /* offset 14763 */
+  "\xe5\xa0\xb2\0" /* offset 14767 */
+  "\xe5\xa0\xb1\0" /* offset 14771 */
+  "\xe5\xa2\xac\0" /* offset 14775 */
+  "\xf0\xa1\x93\xa4\0" /* offset 14779 */
+  "\xe5\xa3\xb2\0" /* offset 14784 */
+  "\xe5\xa3\xb7\0" /* offset 14788 */
+  "\xe5\xa4\x86\0" /* offset 14792 */
+  "\xe5\xa4\x9a\0" /* offset 14796 */
+  "\xe5\xa4\xa2\0" /* offset 14800 */
+  "\xe5\xa5\xa2\0" /* offset 14804 */
+  "\xf0\xa1\x9a\xa8\0" /* offset 14808 */
+  "\xf0\xa1\x9b\xaa\0" /* offset 14813 */
+  "\xe5\xa7\xac\0" /* offset 14818 */
+  "\xe5\xa8\x9b\0" /* offset 14822 */
+  "\xe5\xa8\xa7\0" /* offset 14826 */
+  "\xe5\xa7\x98\0" /* offset 14830 */
+  "\xe5\xa9\xa6\0" /* offset 14834 */
+  "\xe3\x9b\xae\0" /* offset 14838 */
+  "\xf0\xa1\x8d\xaa\0" /* offset 14842 */
+  "\xe5\xac\x88\0" /* offset 14847 */
+  "\xe5\xac\xbe\0" /* offset 14851 */
+  "\xf0\xa1\xa7\x88\0" /* offset 14855 */
+  "\xe5\xaf\x83\0" /* offset 14860 */
+  "\xe5\xaf\x98\0" /* offset 14864 */
+  "\xe5\xaf\xb3\0" /* offset 14868 */
+  "\xf0\xa1\xac\x98\0" /* offset 14872 */
+  "\xe5\xaf\xbf\0" /* offset 14877 */
+  "\xe5\xb0\x86\0" /* offset 14881 */
+  "\xe5\xbc\xb3\0" /* offset 14885 */
+  "\xe3\x9e\x81\0" /* offset 14889 */
+  "\xe5\xb1\xa0\0" /* offset 14893 */
+  "\xe5\xb3\x80\0" /* offset 14897 */
+  "\xe5\xb2\x8d\0" /* offset 14901 */
+  "\xf0\xa1\xb7\xa4\0" /* offset 14905 */
+  "\xe5\xb5\x83\0" /* offset 14910 */
+  "\xf0\xa1\xb7\xa6\0" /* offset 14914 */
+  "\xe5\xb5\xae\0" /* offset 14919 */
+  "\xe5\xb5\xab\0" /* offset 14923 */
+  "\xe5\xb5\xbc\0" /* offset 14927 */
+  "\xe5\xb7\xa1\0" /* offset 14931 */
+  "\xe5\xb7\xa2\0" /* offset 14935 */
+  "\xe3\xa0\xaf\0" /* offset 14939 */
+  "\xe5\xb7\xbd\0" /* offset 14943 */
+  "\xe5\xb8\xa8\0" /* offset 14947 */
+  "\xe5\xb8\xbd\0" /* offset 14951 */
+  "\xe5\xb9\xa9\0" /* offset 14955 */
+  "\xe3\xa1\xa2\0" /* offset 14959 */
+  "\xf0\xa2\x86\x83\0" /* offset 14963 */
+  "\xe3\xa1\xbc\0" /* offset 14968 */
+  "\xe5\xba\xb0\0" /* offset 14972 */
+  "\xe5\xba\xb3\0" /* offset 14976 */
+  "\xe5\xba\xb6\0" /* offset 14980 */
+  "\xf0\xaa\x8e\x92\0" /* offset 14984 */
+  "\xf0\xa2\x8c\xb1\0" /* offset 14989 */
+  "\xe8\x88\x81\0" /* offset 14994 */
+  "\xe5\xbc\xa2\0" /* offset 14998 */
+  "\xe3\xa3\x87\0" /* offset 15002 */
+  "\xf0\xa3\x8a\xb8\0" /* offset 15006 */
+  "\xf0\xa6\x87\x9a\0" /* offset 15011 */
+  "\xe5\xbd\xa2\0" /* offset 15016 */
+  "\xe5\xbd\xab\0" /* offset 15020 */
+  "\xe3\xa3\xa3\0" /* offset 15024 */
+  "\xe5\xbe\x9a\0" /* offset 15028 */
+  "\xe5\xbf\x8d\0" /* offset 15032 */
+  "\xe5\xbf\x97\0" /* offset 15036 */
+  "\xe5\xbf\xb9\0" /* offset 15040 */
+  "\xe6\x82\x81\0" /* offset 15044 */
+  "\xe3\xa4\xba\0" /* offset 15048 */
+  "\xe3\xa4\x9c\0" /* offset 15052 */
+  "\xf0\xa2\x9b\x94\0" /* offset 15056 */
+  "\xe6\x83\x87\0" /* offset 15061 */
+  "\xe6\x85\x88\0" /* offset 15065 */
+  "\xe6\x85\x8c\0" /* offset 15069 */
+  "\xe6\x85\x8e\0" /* offset 15073 */
+  "\xe6\x85\xba\0" /* offset 15077 */
+  "\xe6\x86\xb2\0" /* offset 15081 */
+  "\xe6\x86\xa4\0" /* offset 15085 */
+  "\xe6\x86\xaf\0" /* offset 15089 */
+  "\xe6\x87\x9e\0" /* offset 15093 */
+  "\xe6\x88\x90\0" /* offset 15097 */
+  "\xe6\x88\x9b\0" /* offset 15101 */
+  "\xe6\x89\x9d\0" /* offset 15105 */
+  "\xe6\x8a\xb1\0" /* offset 15109 */
+  "\xe6\x8b\x94\0" /* offset 15113 */
+  "\xe6\x8d\x90\0" /* offset 15117 */
+  "\xf0\xa2\xac\x8c\0" /* offset 15121 */
+  "\xe6\x8c\xbd\0" /* offset 15126 */
+  "\xe6\x8b\xbc\0" /* offset 15130 */
+  "\xe6\x8d\xa8\0" /* offset 15134 */
+  "\xe6\x8e\x83\0" /* offset 15138 */
+  "\xe6\x8f\xa4\0" /* offset 15142 */
+  "\xf0\xa2\xaf\xb1\0" /* offset 15146 */
+  "\xe6\x90\xa2\0" /* offset 15151 */
+  "\xe6\x8f\x85\0" /* offset 15155 */
+  "\xe6\x8e\xa9\0" /* offset 15159 */
+  "\xe3\xa8\xae\0" /* offset 15163 */
+  "\xe6\x91\xa9\0" /* offset 15167 */
+  "\xe6\x91\xbe\0" /* offset 15171 */
+  "\xe6\x92\x9d\0" /* offset 15175 */
+  "\xe6\x91\xb7\0" /* offset 15179 */
+  "\xe3\xa9\xac\0" /* offset 15183 */
+  "\xe6\x95\xac\0" /* offset 15187 */
+  "\xf0\xa3\x80\x8a\0" /* offset 15191 */
+  "\xe6\x97\xa3\0" /* offset 15196 */
+  "\xe6\x9b\xb8\0" /* offset 15200 */
+  "\xe6\x99\x89\0" /* offset 15204 */
+  "\xe3\xac\x99\0" /* offset 15208 */
+  "\xe3\xac\x88\0" /* offset 15212 */
+  "\xe3\xab\xa4\0" /* offset 15216 */
+  "\xe5\x86\x92\0" /* offset 15220 */
+  "\xe5\x86\x95\0" /* offset 15224 */
+  "\xe6\x9c\x80\0" /* offset 15228 */
+  "\xe6\x9a\x9c\0" /* offset 15232 */
+  "\xe8\x82\xad\0" /* offset 15236 */
+  "\xe4\x8f\x99\0" /* offset 15240 */
+  "\xe6\x9c\x9b\0" /* offset 15244 */
+  "\xe6\x9c\xa1\0" /* offset 15248 */
+  "\xe6\x9d\x9e\0" /* offset 15252 */
+  "\xe6\x9d\x93\0" /* offset 15256 */
+  "\xf0\xa3\x8f\x83\0" /* offset 15260 */
+  "\xe3\xad\x89\0" /* offset 15265 */
+  "\xe6\x9f\xba\0" /* offset 15269 */
+  "\xe6\x9e\x85\0" /* offset 15273 */
+  "\xe6\xa1\x92\0" /* offset 15277 */
+  "\xf0\xa3\x91\xad\0" /* offset 15281 */
+  "\xe6\xa2\x8e\0" /* offset 15286 */
+  "\xe6\xa0\x9f\0" /* offset 15290 */
+  "\xe6\xa4\x94\0" /* offset 15294 */
+  "\xe3\xae\x9d\0" /* offset 15298 */
+  "\xe6\xa5\x82\0" /* offset 15302 */
+  "\xe6\xa6\xa3\0" /* offset 15306 */
+  "\xe6\xa7\xaa\0" /* offset 15310 */
+  "\xe6\xaa\xa8\0" /* offset 15314 */
+  "\xf0\xa3\x9a\xa3\0" /* offset 15318 */
+  "\xe6\xab\x9b\0" /* offset 15323 */
+  "\xe3\xb0\x98\0" /* offset 15327 */
+  "\xe6\xac\xa1\0" /* offset 15331 */
+  "\xf0\xa3\xa2\xa7\0" /* offset 15335 */
+  "\xe6\xad\x94\0" /* offset 15340 */
+  "\xe3\xb1\x8e\0" /* offset 15344 */
+  "\xe6\xad\xb2\0" /* offset 15348 */
+  "\xe6\xae\x9f\0" /* offset 15352 */
+  "\xe6\xae\xbb\0" /* offset 15356 */
+  "\xf0\xa3\xaa\x8d\0" /* offset 15360 */
+  "\xf0\xa1\xb4\x8b\0" /* offset 15365 */
+  "\xf0\xa3\xab\xba\0" /* offset 15370 */
+  "\xe6\xb1\x8e\0" /* offset 15375 */
+  "\xf0\xa3\xb2\xbc\0" /* offset 15379 */
+  "\xe6\xb2\xbf\0" /* offset 15384 */
+  "\xe6\xb3\x8d\0" /* offset 15388 */
+  "\xe6\xb1\xa7\0" /* offset 15392 */
+  "\xe6\xb4\x96\0" /* offset 15396 */
+  "\xe6\xb4\xbe\0" /* offset 15400 */
+  "\xe6\xb5\xa9\0" /* offset 15404 */
+  "\xe6\xb5\xb8\0" /* offset 15408 */
+  "\xe6\xb6\x85\0" /* offset 15412 */
+  "\xf0\xa3\xb4\x9e\0" /* offset 15416 */
+  "\xe6\xb4\xb4\0" /* offset 15421 */
+  "\xe6\xb8\xaf\0" /* offset 15425 */
+  "\xe6\xb9\xae\0" /* offset 15429 */
+  "\xe3\xb4\xb3\0" /* offset 15433 */
+  "\xe6\xbb\x8b\0" /* offset 15437 */
+  "\xe6\xbb\x87\0" /* offset 15441 */
+  "\xf0\xa3\xbb\x91\0" /* offset 15445 */
+  "\xe6\xb7\xb9\0" /* offset 15450 */
+  "\xe6\xbd\xae\0" /* offset 15454 */
+  "\xf0\xa3\xbd\x9e\0" /* offset 15458 */
+  "\xf0\xa3\xbe\x8e\0" /* offset 15463 */
+  "\xe6\xbf\x86\0" /* offset 15468 */
+  "\xe7\x80\xb9\0" /* offset 15472 */
+  "\xe7\x80\x9e\0" /* offset 15476 */
+  "\xe7\x80\x9b\0" /* offset 15480 */
+  "\xe3\xb6\x96\0" /* offset 15484 */
+  "\xe7\x81\x8a\0" /* offset 15488 */
+  "\xe7\x81\xbd\0" /* offset 15492 */
+  "\xe7\x81\xb7\0" /* offset 15496 */
+  "\xe7\x82\xad\0" /* offset 15500 */
+  "\xf0\xa0\x94\xa5\0" /* offset 15504 */
+  "\xe7\x85\x85\0" /* offset 15509 */
+  "\xf0\xa4\x89\xa3\0" /* offset 15513 */
+  "\xe7\x86\x9c\0" /* offset 15518 */
+  "\xe4\x8e\xab\0" /* offset 15522 */
+  "\xe7\x88\xa8\0" /* offset 15526 */
+  "\xe7\x88\xb5\0" /* offset 15530 */
+  "\xe7\x89\x90\0" /* offset 15534 */
+  "\xf0\xa4\x98\x88\0" /* offset 15538 */
+  "\xe7\x8a\x80\0" /* offset 15543 */
+  "\xe7\x8a\x95\0" /* offset 15547 */
+  "\xf0\xa4\x9c\xb5\0" /* offset 15551 */
+  "\xf0\xa4\xa0\x94\0" /* offset 15556 */
+  "\xe7\x8d\xba\0" /* offset 15561 */
+  "\xe7\x8e\x8b\0" /* offset 15565 */
+  "\xe3\xba\xac\0" /* offset 15569 */
+  "\xe7\x8e\xa5\0" /* offset 15573 */
+  "\xe3\xba\xb8\0" /* offset 15577 */
+  "\xe7\x91\x87\0" /* offset 15581 */
+  "\xe7\x91\x9c\0" /* offset 15585 */
+  "\xe7\x91\xb1\0" /* offset 15589 */
+  "\xe7\x92\x85\0" /* offset 15593 */
+  "\xe7\x93\x8a\0" /* offset 15597 */
+  "\xe3\xbc\x9b\0" /* offset 15601 */
+  "\xe7\x94\xa4\0" /* offset 15605 */
+  "\xf0\xa4\xb0\xb6\0" /* offset 15609 */
+  "\xe7\x94\xbe\0" /* offset 15614 */
+  "\xf0\xa4\xb2\x92\0" /* offset 15618 */
+  "\xf0\xa2\x86\x9f\0" /* offset 15623 */
+  "\xe7\x98\x90\0" /* offset 15628 */
+  "\xf0\xa4\xbe\xa1\0" /* offset 15632 */
+  "\xf0\xa4\xbe\xb8\0" /* offset 15637 */
+  "\xf0\xa5\x81\x84\0" /* offset 15642 */
+  "\xe3\xbf\xbc\0" /* offset 15647 */
+  "\xe4\x80\x88\0" /* offset 15651 */
+  "\xe7\x9b\xb4\0" /* offset 15655 */
+  "\xf0\xa5\x83\xb3\0" /* offset 15659 */
+  "\xf0\xa5\x83\xb2\0" /* offset 15664 */
+  "\xf0\xa5\x84\x99\0" /* offset 15669 */
+  "\xf0\xa5\x84\xb3\0" /* offset 15674 */
+  "\xe7\x9c\x9e\0" /* offset 15679 */
+  "\xe7\x9c\x9f\0" /* offset 15683 */
+  "\xe7\x9d\x8a\0" /* offset 15687 */
+  "\xe4\x80\xb9\0" /* offset 15691 */
+  "\xe7\x9e\x8b\0" /* offset 15695 */
+  "\xe4\x81\x86\0" /* offset 15699 */
+  "\xe4\x82\x96\0" /* offset 15703 */
+  "\xf0\xa5\x90\x9d\0" /* offset 15707 */
+  "\xe7\xa1\x8e\0" /* offset 15712 */
+  "\xe7\xa3\x8c\0" /* offset 15716 */
+  "\xe4\x83\xa3\0" /* offset 15720 */
+  "\xf0\xa5\x98\xa6\0" /* offset 15724 */
+  "\xf0\xa5\x9a\x9a\0" /* offset 15729 */
+  "\xf0\xa5\x9b\x85\0" /* offset 15734 */
+  "\xe7\xa7\xab\0" /* offset 15739 */
+  "\xe4\x84\xaf\0" /* offset 15743 */
+  "\xe7\xa9\x8a\0" /* offset 15747 */
+  "\xe7\xa9\x8f\0" /* offset 15751 */
+  "\xf0\xa5\xa5\xbc\0" /* offset 15755 */
+  "\xf0\xa5\xaa\xa7\0" /* offset 15760 */
+  "\xe7\xaa\xae\0" /* offset 15765 */
+  "\xe4\x88\x82\0" /* offset 15769 */
+  "\xf0\xa5\xae\xab\0" /* offset 15773 */
+  "\xe7\xaf\x86\0" /* offset 15778 */
+  "\xe7\xaf\x89\0" /* offset 15782 */
+  "\xe4\x88\xa7\0" /* offset 15786 */
+  "\xf0\xa5\xb2\x80\0" /* offset 15790 */
+  "\xe7\xb3\x92\0" /* offset 15795 */
+  "\xe4\x8a\xa0\0" /* offset 15799 */
+  "\xe7\xb3\xa8\0" /* offset 15803 */
+  "\xe7\xb3\xa3\0" /* offset 15807 */
+  "\xe7\xb4\x80\0" /* offset 15811 */
+  "\xf0\xa5\xbe\x86\0" /* offset 15815 */
+  "\xe7\xb5\xa3\0" /* offset 15820 */
+  "\xe4\x8c\x81\0" /* offset 15824 */
+  "\xe7\xb7\x87\0" /* offset 15828 */
+  "\xe7\xb8\x82\0" /* offset 15832 */
+  "\xe7\xb9\x85\0" /* offset 15836 */
+  "\xe4\x8c\xb4\0" /* offset 15840 */
+  "\xf0\xa6\x88\xa8\0" /* offset 15844 */
+  "\xf0\xa6\x89\x87\0" /* offset 15849 */
+  "\xe4\x8d\x99\0" /* offset 15854 */
+  "\xf0\xa6\x8b\x99\0" /* offset 15858 */
+  "\xe7\xbd\xba\0" /* offset 15863 */
+  "\xf0\xa6\x8c\xbe\0" /* offset 15867 */
+  "\xe7\xbe\x95\0" /* offset 15872 */
+  "\xe7\xbf\xba\0" /* offset 15876 */
+  "\xf0\xa6\x93\x9a\0" /* offset 15880 */
+  "\xf0\xa6\x94\xa3\0" /* offset 15885 */
+  "\xe8\x81\xa0\0" /* offset 15890 */
+  "\xf0\xa6\x96\xa8\0" /* offset 15894 */
+  "\xe8\x81\xb0\0" /* offset 15899 */
+  "\xf0\xa3\x8d\x9f\0" /* offset 15903 */
+  "\xe4\x8f\x95\0" /* offset 15908 */
+  "\xe8\x82\xb2\0" /* offset 15912 */
+  "\xe8\x84\x83\0" /* offset 15916 */
+  "\xe4\x90\x8b\0" /* offset 15920 */
+  "\xe8\x84\xbe\0" /* offset 15924 */
+  "\xe5\xaa\xb5\0" /* offset 15928 */
+  "\xf0\xa6\x9e\xa7\0" /* offset 15932 */
+  "\xf0\xa6\x9e\xb5\0" /* offset 15937 */
+  "\xf0\xa3\x8e\x93\0" /* offset 15942 */
+  "\xf0\xa3\x8e\x9c\0" /* offset 15947 */
+  "\xe8\x88\x84\0" /* offset 15952 */
+  "\xe8\xbe\x9e\0" /* offset 15956 */
+  "\xe4\x91\xab\0" /* offset 15960 */
+  "\xe8\x8a\x91\0" /* offset 15964 */
+  "\xe8\x8a\x8b\0" /* offset 15968 */
+  "\xe8\x8a\x9d\0" /* offset 15972 */
+  "\xe5\x8a\xb3\0" /* offset 15976 */
+  "\xe8\x8a\xb1\0" /* offset 15980 */
+  "\xe8\x8a\xb3\0" /* offset 15984 */
+  "\xe8\x8a\xbd\0" /* offset 15988 */
+  "\xe8\x8b\xa6\0" /* offset 15992 */
+  "\xf0\xa6\xac\xbc\0" /* offset 15996 */
+  "\xe8\x8c\x9d\0" /* offset 16001 */
+  "\xe8\x8d\xa3\0" /* offset 16005 */
+  "\xe8\x8e\xad\0" /* offset 16009 */
+  "\xe8\x8c\xa3\0" /* offset 16013 */
+  "\xe8\x8e\xbd\0" /* offset 16017 */
+  "\xe8\x8f\xa7\0" /* offset 16021 */
+  "\xe8\x8d\x93\0" /* offset 16025 */
+  "\xe8\x8f\x8a\0" /* offset 16029 */
+  "\xe8\x8f\x8c\0" /* offset 16033 */
+  "\xe8\x8f\x9c\0" /* offset 16037 */
+  "\xf0\xa6\xb0\xb6\0" /* offset 16041 */
+  "\xf0\xa6\xb5\xab\0" /* offset 16046 */
+  "\xf0\xa6\xb3\x95\0" /* offset 16051 */
+  "\xe4\x94\xab\0" /* offset 16056 */
+  "\xe8\x93\xb1\0" /* offset 16060 */
+  "\xe8\x93\xb3\0" /* offset 16064 */
+  "\xe8\x94\x96\0" /* offset 16068 */
+  "\xf0\xa7\x8f\x8a\0" /* offset 16072 */
+  "\xe8\x95\xa4\0" /* offset 16077 */
+  "\xf0\xa6\xbc\xac\0" /* offset 16081 */
+  "\xe4\x95\x9d\0" /* offset 16086 */
+  "\xe4\x95\xa1\0" /* offset 16090 */
+  "\xf0\xa6\xbe\xb1\0" /* offset 16094 */
+  "\xf0\xa7\x83\x92\0" /* offset 16099 */
+  "\xe4\x95\xab\0" /* offset 16104 */
+  "\xe8\x99\x90\0" /* offset 16108 */
+  "\xe8\x99\xa7\0" /* offset 16112 */
+  "\xe8\x99\xa9\0" /* offset 16116 */
+  "\xe8\x9a\xa9\0" /* offset 16120 */
+  "\xe8\x9a\x88\0" /* offset 16124 */
+  "\xe8\x9c\x8e\0" /* offset 16128 */
+  "\xe8\x9b\xa2\0" /* offset 16132 */
+  "\xe8\x9d\xb9\0" /* offset 16136 */
+  "\xe8\x9c\xa8\0" /* offset 16140 */
+  "\xe8\x9d\xab\0" /* offset 16144 */
+  "\xe8\x9e\x86\0" /* offset 16148 */
+  "\xe4\xb5\x97\0" /* offset 16152 */
+  "\xe8\x9f\xa1\0" /* offset 16156 */
+  "\xe8\xa0\x81\0" /* offset 16160 */
+  "\xe4\x97\xb9\0" /* offset 16164 */
+  "\xe8\xa1\xa0\0" /* offset 16168 */
+  "\xf0\xa7\x99\xa7\0" /* offset 16172 */
+  "\xe8\xa3\x97\0" /* offset 16177 */
+  "\xe8\xa3\x9e\0" /* offset 16181 */
+  "\xe4\x98\xb5\0" /* offset 16185 */
+  "\xe8\xa3\xba\0" /* offset 16189 */
+  "\xe3\x92\xbb\0" /* offset 16193 */
+  "\xf0\xa7\xa2\xae\0" /* offset 16197 */
+  "\xf0\xa7\xa5\xa6\0" /* offset 16202 */
+  "\xe4\x9a\xbe\0" /* offset 16207 */
+  "\xe4\x9b\x87\0" /* offset 16211 */
+  "\xe8\xaa\xa0\0" /* offset 16215 */
+  "\xe8\xab\xad\0" /* offset 16219 */
+  "\xe8\xae\x8a\0" /* offset 16223 */
+  "\xf0\xa7\xb2\xa8\0" /* offset 16227 */
+  "\xe8\xb2\xab\0" /* offset 16232 */
+  "\xe8\xb3\x81\0" /* offset 16236 */
+  "\xe8\xb4\x9b\0" /* offset 16240 */
+  "\xe8\xb5\xb7\0" /* offset 16244 */
+  "\xf0\xa7\xbc\xaf\0" /* offset 16248 */
+  "\xf0\xa0\xa0\x84\0" /* offset 16253 */
+  "\xe8\xb7\x8b\0" /* offset 16258 */
+  "\xe8\xb6\xbc\0" /* offset 16262 */
+  "\xe8\xb7\xb0\0" /* offset 16266 */
+  "\xf0\xa0\xa3\x9e\0" /* offset 16270 */
+  "\xe8\xbb\x94\0" /* offset 16275 */
+  "\xe8\xbc\xb8\0" /* offset 16279 */
+  "\xf0\xa8\x97\x92\0" /* offset 16283 */
+  "\xf0\xa8\x97\xad\0" /* offset 16288 */
+  "\xe9\x82\x94\0" /* offset 16293 */
+  "\xe9\x83\xb1\0" /* offset 16297 */
+  "\xe9\x84\x91\0" /* offset 16301 */
+  "\xf0\xa8\x9c\xae\0" /* offset 16305 */
+  "\xe9\x84\x9b\0" /* offset 16310 */
+  "\xe9\x88\xb8\0" /* offset 16314 */
+  "\xe9\x8b\x97\0" /* offset 16318 */
+  "\xe9\x8b\x98\0" /* offset 16322 */
+  "\xe9\x89\xbc\0" /* offset 16326 */
+  "\xe9\x8f\xb9\0" /* offset 16330 */
+  "\xe9\x90\x95\0" /* offset 16334 */
+  "\xf0\xa8\xaf\xba\0" /* offset 16338 */
+  "\xe9\x96\x8b\0" /* offset 16343 */
+  "\xe4\xa6\x95\0" /* offset 16347 */
+  "\xe9\x96\xb7\0" /* offset 16351 */
+  "\xf0\xa8\xb5\xb7\0" /* offset 16355 */
+  "\xe4\xa7\xa6\0" /* offset 16360 */
+  "\xe9\x9b\x83\0" /* offset 16364 */
+  "\xe5\xb6\xb2\0" /* offset 16368 */
+  "\xe9\x9c\xa3\0" /* offset 16372 */
+  "\xf0\xa9\x85\x85\0" /* offset 16376 */
+  "\xf0\xa9\x88\x9a\0" /* offset 16381 */
+  "\xe4\xa9\xae\0" /* offset 16386 */
+  "\xe4\xa9\xb6\0" /* offset 16390 */
+  "\xe9\x9f\xa0\0" /* offset 16394 */
+  "\xf0\xa9\x90\x8a\0" /* offset 16398 */
+  "\xe4\xaa\xb2\0" /* offset 16403 */
+  "\xf0\xa9\x92\x96\0" /* offset 16407 */
+  "\xe9\xa0\x8b\0" /* offset 16412 */
+  "\xe9\xa0\xa9\0" /* offset 16416 */
+  "\xf0\xa9\x96\xb6\0" /* offset 16420 */
+  "\xe9\xa3\xa2\0" /* offset 16425 */
+  "\xe4\xac\xb3\0" /* offset 16429 */
+  "\xe9\xa4\xa9\0" /* offset 16433 */
+  "\xe9\xa6\xa7\0" /* offset 16437 */
+  "\xe9\xa7\x82\0" /* offset 16441 */
+  "\xe9\xa7\xbe\0" /* offset 16445 */
+  "\xe4\xaf\x8e\0" /* offset 16449 */
+  "\xf0\xa9\xac\xb0\0" /* offset 16453 */
+  "\xe9\xac\x92\0" /* offset 16458 */
+  "\xe9\xb1\x80\0" /* offset 16462 */
+  "\xe9\xb3\xbd\0" /* offset 16466 */
+  "\xe4\xb3\x8e\0" /* offset 16470 */
+  "\xe4\xb3\xad\0" /* offset 16474 */
+  "\xe9\xb5\xa7\0" /* offset 16478 */
+  "\xf0\xaa\x83\x8e\0" /* offset 16482 */
+  "\xe4\xb3\xb8\0" /* offset 16487 */
+  "\xf0\xaa\x84\x85\0" /* offset 16491 */
+  "\xf0\xaa\x88\x8e\0" /* offset 16496 */
+  "\xf0\xaa\x8a\x91\0" /* offset 16501 */
+  "\xe4\xb5\x96\0" /* offset 16506 */
+  "\xe9\xbb\xbe\0" /* offset 16510 */
+  "\xe9\xbc\x85\0" /* offset 16514 */
+  "\xe9\xbc\x8f\0" /* offset 16518 */
+  "\xe9\xbc\x96\0" /* offset 16522 */
+  "\xf0\xaa\x98\x80\0" /* offset 16526 */;
+
+#endif /* DECOMP_H */
diff --git a/lib/contrib/nfkc.c b/lib/contrib/nfkc.c
new file mode 100644 (file)
index 0000000..e5eb4d0
--- /dev/null
@@ -0,0 +1,1054 @@
+/* nfkc.c      Unicode normalization utilities.
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "stringprep.h"
+
+/* 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.
+ */
+
+/* Hacks to make syncing with GLIB code easier. */
+#define gboolean int
+#define gchar char
+#define guchar unsigned char
+#define glong long
+#define gint int
+#define guint unsigned int
+#define gushort unsigned short
+#define gint16 int16_t
+#define guint16 uint16_t
+#define gunichar uint32_t
+#define gsize size_t
+#define gssize ssize_t
+#define g_malloc malloc
+#define g_free free
+#define GError void
+#define g_set_error(a,b,c,d) ((void) 0)
+#define g_new(struct_type, n_structs)                                  \
+  ((struct_type *) g_malloc (((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
+#  if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
+#    define G_STMT_START       (void)(
+#    define G_STMT_END         )
+#  else
+#    if (defined (sun) || defined (__sun__))
+#      define G_STMT_START     if (1)
+#      define G_STMT_END       else (void)0
+#    else
+#      define G_STMT_START     do
+#      define G_STMT_END       while (0)
+#    endif
+#  endif
+#define g_return_val_if_fail(expr,val)         G_STMT_START{ (void)0; }G_STMT_END
+#define G_N_ELEMENTS(arr)              (sizeof (arr) / sizeof ((arr)[0]))
+#define TRUE 1
+#define FALSE 0
+
+/* Code from GLIB gunicode.h starts here. */
+
+typedef enum
+{
+  G_NORMALIZE_DEFAULT,
+  G_NORMALIZE_NFD = G_NORMALIZE_DEFAULT,
+  G_NORMALIZE_DEFAULT_COMPOSE,
+  G_NORMALIZE_NFC = G_NORMALIZE_DEFAULT_COMPOSE,
+  G_NORMALIZE_ALL,
+  G_NORMALIZE_NFKD = G_NORMALIZE_ALL,
+  G_NORMALIZE_ALL_COMPOSE,
+  G_NORMALIZE_NFKC = G_NORMALIZE_ALL_COMPOSE
+}
+GNormalizeMode;
+
+/* Code from GLIB gutf8.c starts here. */
+
+#define UTF8_COMPUTE(Char, Mask, Len)          \
+  if (Char < 128)                              \
+    {                                          \
+      Len = 1;                                 \
+      Mask = 0x7f;                             \
+    }                                          \
+  else if ((Char & 0xe0) == 0xc0)              \
+    {                                          \
+      Len = 2;                                 \
+      Mask = 0x1f;                             \
+    }                                          \
+  else if ((Char & 0xf0) == 0xe0)              \
+    {                                          \
+      Len = 3;                                 \
+      Mask = 0x0f;                             \
+    }                                          \
+  else if ((Char & 0xf8) == 0xf0)              \
+    {                                          \
+      Len = 4;                                 \
+      Mask = 0x07;                             \
+    }                                          \
+  else if ((Char & 0xfc) == 0xf8)              \
+    {                                          \
+      Len = 5;                                 \
+      Mask = 0x03;                             \
+    }                                          \
+  else if ((Char & 0xfe) == 0xfc)              \
+    {                                          \
+      Len = 6;                                 \
+      Mask = 0x01;                             \
+    }                                          \
+  else                                         \
+    Len = -1;
+
+#define UTF8_LENGTH(Char)                      \
+  ((Char) < 0x80 ? 1 :                         \
+   ((Char) < 0x800 ? 2 :                       \
+    ((Char) < 0x10000 ? 3 :                    \
+     ((Char) < 0x200000 ? 4 :                  \
+      ((Char) < 0x4000000 ? 5 : 6)))))
+
+
+#define UTF8_GET(Result, Chars, Count, Mask, Len)      \
+  (Result) = (Chars)[0] & (Mask);                      \
+  for ((Count) = 1; (Count) < (Len); ++(Count))                \
+    {                                                  \
+      if (((Chars)[(Count)] & 0xc0) != 0x80)           \
+       {                                               \
+         (Result) = -1;                                \
+         break;                                        \
+       }                                               \
+      (Result) <<= 6;                                  \
+      (Result) |= ((Chars)[(Count)] & 0x3f);           \
+    }
+
+#define UNICODE_VALID(Char)                    \
+  ((Char) < 0x110000 &&                                \
+   (((Char) & 0xFFFFF800) != 0xD800) &&                \
+   ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&     \
+   ((Char) & 0xFFFE) != 0xFFFE)
+
+
+static const gchar utf8_skip_data[256] = {
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1, 1, 1, 1, 1, 1, 1,
+  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+  2, 2, 2, 2, 2, 2, 2,
+  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+  5, 5, 5, 6, 6, 1, 1
+};
+
+static const gchar *const g_utf8_skip = utf8_skip_data;
+
+#define g_utf8_next_char(p) (char *)((p) + g_utf8_skip[*(guchar *)(p)])
+
+/*
+ * g_utf8_strlen:
+ * @p: pointer to the start of a UTF-8 encoded string.
+ * @max: the maximum number of bytes to examine. If @max
+ *       is less than 0, then the string is assumed to be
+ *       nul-terminated. If @max is 0, @p will not be examined and
+ *       may be %NULL.
+ *
+ * Returns the length of the string in characters.
+ *
+ * Return value: the length of the string in characters
+ **/
+static glong
+g_utf8_strlen (const gchar * p, gssize max)
+{
+  glong len = 0;
+  const gchar *start = p;
+  g_return_val_if_fail (p != NULL || max == 0, 0);
+
+  if (max < 0)
+    {
+      while (*p)
+       {
+         p = g_utf8_next_char (p);
+         ++len;
+       }
+    }
+  else
+    {
+      if (max == 0 || !*p)
+       return 0;
+
+      p = g_utf8_next_char (p);
+
+      while (p - start < max && *p)
+       {
+         ++len;
+         p = g_utf8_next_char (p);
+       }
+
+      /* only do the last len increment if we got a complete
+       * char (don't count partial chars)
+       */
+      if (p - start == max)
+       ++len;
+    }
+
+  return len;
+}
+
+/*
+ * g_utf8_get_char:
+ * @p: a pointer to Unicode character encoded as UTF-8
+ *
+ * Converts a sequence of bytes encoded as UTF-8 to a Unicode character.
+ * If @p does not point to a valid UTF-8 encoded character, results are
+ * undefined. If you are not sure that the bytes are complete
+ * valid Unicode characters, you should use g_utf8_get_char_validated()
+ * instead.
+ *
+ * Return value: the resulting character
+ **/
+static gunichar
+g_utf8_get_char (const gchar * p)
+{
+  int i, mask = 0, len;
+  gunichar result;
+  unsigned char c = (unsigned char) *p;
+
+  UTF8_COMPUTE (c, mask, len);
+  if (len == -1)
+    return (gunichar) - 1;
+  UTF8_GET (result, p, i, mask, len);
+
+  return result;
+}
+
+/*
+ * g_unichar_to_utf8:
+ * @c: a ISO10646 character code
+ * @outbuf: output buffer, must have at least 6 bytes of space.
+ *       If %NULL, the length will be computed and returned
+ *       and nothing will be written to @outbuf.
+ *
+ * Converts a single character to UTF-8.
+ *
+ * Return value: number of bytes written
+ **/
+static int
+g_unichar_to_utf8 (gunichar c, gchar * outbuf)
+{
+  guint len = 0;
+  int first;
+  int i;
+
+  if (c < 0x80)
+    {
+      first = 0;
+      len = 1;
+    }
+  else if (c < 0x800)
+    {
+      first = 0xc0;
+      len = 2;
+    }
+  else if (c < 0x10000)
+    {
+      first = 0xe0;
+      len = 3;
+    }
+  else if (c < 0x200000)
+    {
+      first = 0xf0;
+      len = 4;
+    }
+  else if (c < 0x4000000)
+    {
+      first = 0xf8;
+      len = 5;
+    }
+  else
+    {
+      first = 0xfc;
+      len = 6;
+    }
+
+  if (outbuf)
+    {
+      for (i = len - 1; i > 0; --i)
+       {
+         outbuf[i] = (c & 0x3f) | 0x80;
+         c >>= 6;
+       }
+      outbuf[0] = c | first;
+    }
+
+  return len;
+}
+
+/*
+ * g_utf8_to_ucs4_fast:
+ * @str: a UTF-8 encoded string
+ * @len: the maximum length of @str to use. If @len < 0, then
+ *       the string is nul-terminated.
+ * @items_written: location to store the number of characters in the
+ *                 result, or %NULL.
+ *
+ * Convert a string from UTF-8 to a 32-bit fixed width
+ * representation as UCS-4, assuming valid UTF-8 input.
+ * This function is roughly twice as fast as g_utf8_to_ucs4()
+ * but does no error checking on the input.
+ *
+ * Return value: a pointer to a newly allocated UCS-4 string.
+ *               This value must be freed with g_free().
+ **/
+static gunichar *
+g_utf8_to_ucs4_fast (const gchar * str, glong len, glong * items_written)
+{
+  gint j, charlen;
+  gunichar *result;
+  gint n_chars, i;
+  const gchar *p;
+
+  g_return_val_if_fail (str != NULL, NULL);
+
+  p = str;
+  n_chars = 0;
+  if (len < 0)
+    {
+      while (*p)
+       {
+         p = g_utf8_next_char (p);
+         ++n_chars;
+       }
+    }
+  else
+    {
+      while (p < str + len && *p)
+       {
+         p = g_utf8_next_char (p);
+         ++n_chars;
+       }
+    }
+
+  result = g_new (gunichar, n_chars + 1);
+  if (!result)
+    return NULL;
+
+  p = str;
+  for (i = 0; i < n_chars; i++)
+    {
+      gunichar wc = ((unsigned char *) p)[0];
+
+      if (wc < 0x80)
+       {
+         result[i] = wc;
+         p++;
+       }
+      else
+       {
+         if (wc < 0xe0)
+           {
+             charlen = 2;
+             wc &= 0x1f;
+           }
+         else if (wc < 0xf0)
+           {
+             charlen = 3;
+             wc &= 0x0f;
+           }
+         else if (wc < 0xf8)
+           {
+             charlen = 4;
+             wc &= 0x07;
+           }
+         else if (wc < 0xfc)
+           {
+             charlen = 5;
+             wc &= 0x03;
+           }
+         else
+           {
+             charlen = 6;
+             wc &= 0x01;
+           }
+
+         for (j = 1; j < charlen; j++)
+           {
+             wc <<= 6;
+             wc |= ((unsigned char *) p)[j] & 0x3f;
+           }
+
+         result[i] = wc;
+         p += charlen;
+       }
+    }
+  result[i] = 0;
+
+  if (items_written)
+    *items_written = i;
+
+  return result;
+}
+
+/*
+ * g_ucs4_to_utf8:
+ * @str: a UCS-4 encoded string
+ * @len: the maximum length of @str to use. If @len < 0, then
+ *       the string is terminated with a 0 character.
+ * @items_read: location to store number of characters read read, or %NULL.
+ * @items_written: location to store number of bytes written or %NULL.
+ *                 The value here stored does not include the trailing 0
+ *                 byte.
+ * @error: location to store the error occuring, or %NULL to ignore
+ *         errors. Any of the errors in #GConvertError other than
+ *         %G_CONVERT_ERROR_NO_CONVERSION may occur.
+ *
+ * Convert a string from a 32-bit fixed width representation as UCS-4.
+ * to UTF-8. The result will be terminated with a 0 byte.
+ *
+ * Return value: a pointer to a newly allocated UTF-8 string.
+ *               This value must be freed with g_free(). If an
+ *               error occurs, %NULL will be returned and
+ *               @error set.
+ **/
+static gchar *
+g_ucs4_to_utf8 (const gunichar * str,
+               glong len,
+               glong * items_read, glong * items_written, GError ** error)
+{
+  gint result_length;
+  gchar *result = NULL;
+  gchar *p;
+  gint i;
+
+  result_length = 0;
+  for (i = 0; len < 0 || i < len; i++)
+    {
+      if (!str[i])
+       break;
+
+      if (str[i] >= 0x80000000)
+       {
+         if (items_read)
+           *items_read = i;
+
+         g_set_error (error, G_CONVERT_ERROR,
+                      G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
+                      _("Character out of range for UTF-8"));
+         goto err_out;
+       }
+
+      result_length += UTF8_LENGTH (str[i]);
+    }
+
+  result = g_malloc (result_length + 1);
+  if (!result)
+    return NULL;
+  p = result;
+
+  i = 0;
+  while (p < result + result_length)
+    p += g_unichar_to_utf8 (str[i++], p);
+
+  *p = '\0';
+
+  if (items_written)
+    *items_written = p - result;
+
+err_out:
+  if (items_read)
+    *items_read = i;
+
+  return result;
+}
+
+/* Code from GLIB gunidecomp.c starts here. */
+
+#include "gunidecomp.h"
+#include "gunicomp.h"
+
+#define CC_PART1(Page, Char) \
+  ((combining_class_table_part1[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
+   ? (combining_class_table_part1[Page] - G_UNICODE_MAX_TABLE_INDEX) \
+   : (cclass_data[combining_class_table_part1[Page]][Char]))
+
+#define CC_PART2(Page, Char) \
+  ((combining_class_table_part2[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
+   ? (combining_class_table_part2[Page] - G_UNICODE_MAX_TABLE_INDEX) \
+   : (cclass_data[combining_class_table_part2[Page]][Char]))
+
+#define COMBINING_CLASS(Char) \
+  (((Char) <= G_UNICODE_LAST_CHAR_PART1) \
+   ? CC_PART1 ((Char) >> 8, (Char) & 0xff) \
+   : (((Char) >= 0xe0000 && (Char) <= G_UNICODE_LAST_CHAR) \
+      ? CC_PART2 (((Char) - 0xe0000) >> 8, (Char) & 0xff) \
+      : 0))
+
+/* constants for hangul syllable [de]composition */
+#define SBase 0xAC00
+#define LBase 0x1100
+#define VBase 0x1161
+#define TBase 0x11A7
+#define LCount 19
+#define VCount 21
+#define TCount 28
+#define NCount (VCount * TCount)
+#define SCount (LCount * NCount)
+
+/*
+ * g_unicode_canonical_ordering:
+ * @string: a UCS-4 encoded string.
+ * @len: the maximum length of @string to use.
+ *
+ * Computes the canonical ordering of a string in-place.
+ * This rearranges decomposed characters in the string
+ * according to their combining classes.  See the Unicode
+ * manual for more information.
+ **/
+static void
+g_unicode_canonical_ordering (gunichar * string, gsize len)
+{
+  gsize i;
+  int swap = 1;
+
+  while (swap)
+    {
+      int last;
+      swap = 0;
+      last = COMBINING_CLASS (string[0]);
+      for (i = 0; i < len - 1; ++i)
+       {
+         int next = COMBINING_CLASS (string[i + 1]);
+         if (next != 0 && last > next)
+           {
+             gsize j;
+             /* Percolate item leftward through string.  */
+             for (j = i + 1; j > 0; --j)
+               {
+                 gunichar t;
+                 if (COMBINING_CLASS (string[j - 1]) <= next)
+                   break;
+                 t = string[j];
+                 string[j] = string[j - 1];
+                 string[j - 1] = t;
+                 swap = 1;
+               }
+             /* We're re-entering the loop looking at the old
+                character again.  */
+             next = last;
+           }
+         last = next;
+       }
+    }
+}
+
+/* http://www.unicode.org/unicode/reports/tr15/#Hangul
+ * r should be null or have sufficient space. Calling with r == NULL will
+ * only calculate the result_len; however, a buffer with space for three
+ * characters will always be big enough. */
+static void
+decompose_hangul (gunichar s, gunichar * r, gsize * result_len)
+{
+  gint SIndex = s - SBase;
+
+  /* not a hangul syllable */
+  if (SIndex < 0 || SIndex >= SCount)
+    {
+      if (r)
+       r[0] = s;
+      *result_len = 1;
+    }
+  else
+    {
+      gunichar L = LBase + SIndex / NCount;
+      gunichar V = VBase + (SIndex % NCount) / TCount;
+      gunichar T = TBase + SIndex % TCount;
+
+      if (r)
+       {
+         r[0] = L;
+         r[1] = V;
+       }
+
+      if (T != TBase)
+       {
+         if (r)
+           r[2] = T;
+         *result_len = 3;
+       }
+      else
+       *result_len = 2;
+    }
+}
+
+/* returns a pointer to a null-terminated UTF-8 string */
+static const gchar *
+find_decomposition (gunichar ch, gboolean compat)
+{
+  int start = 0;
+  int end = G_N_ELEMENTS (decomp_table);
+
+  if (ch >= decomp_table[start].ch && ch <= decomp_table[end - 1].ch)
+    {
+      while (TRUE)
+       {
+         int half = (start + end) / 2;
+         if (ch == decomp_table[half].ch)
+           {
+             int offset;
+
+             if (compat)
+               {
+                 offset = decomp_table[half].compat_offset;
+                 if (offset == G_UNICODE_NOT_PRESENT_OFFSET)
+                   offset = decomp_table[half].canon_offset;
+               }
+             else
+               {
+                 offset = decomp_table[half].canon_offset;
+                 if (offset == G_UNICODE_NOT_PRESENT_OFFSET)
+                   return NULL;
+               }
+
+             return &(decomp_expansion_string[offset]);
+           }
+         else if (half == start)
+           break;
+         else if (ch > decomp_table[half].ch)
+           start = half;
+         else
+           end = half;
+       }
+    }
+
+  return NULL;
+}
+
+/* L,V => LV and LV,T => LVT  */
+static gboolean
+combine_hangul (gunichar a, gunichar b, gunichar * result)
+{
+  gint LIndex = a - LBase;
+  gint SIndex = a - SBase;
+
+  gint VIndex = b - VBase;
+  gint TIndex = b - TBase;
+
+  if (0 <= LIndex && LIndex < LCount && 0 <= VIndex && VIndex < VCount)
+    {
+      *result = SBase + (LIndex * VCount + VIndex) * TCount;
+      return TRUE;
+    }
+  else if (0 <= SIndex && SIndex < SCount && (SIndex % TCount) == 0
+          && 0 <= TIndex && TIndex <= TCount)
+    {
+      *result = a + TIndex;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+#define CI(Page, Char) \
+  ((compose_table[Page] >= G_UNICODE_MAX_TABLE_INDEX) \
+   ? (compose_table[Page] - G_UNICODE_MAX_TABLE_INDEX) \
+   : (compose_data[compose_table[Page]][Char]))
+
+#define COMPOSE_INDEX(Char) \
+     ((((Char) >> 8) > (COMPOSE_TABLE_LAST)) ? 0 : CI((Char) >> 8, (Char) & 0xff))
+
+static gboolean
+combine (gunichar a, gunichar b, gunichar * result)
+{
+  gushort index_a, index_b;
+
+  if (combine_hangul (a, b, result))
+    return TRUE;
+
+  index_a = COMPOSE_INDEX (a);
+
+  if (index_a >= COMPOSE_FIRST_SINGLE_START && index_a < COMPOSE_SECOND_START)
+    {
+      if (b == compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][0])
+       {
+         *result =
+           compose_first_single[index_a - COMPOSE_FIRST_SINGLE_START][1];
+         return TRUE;
+       }
+      else
+       return FALSE;
+    }
+
+  index_b = COMPOSE_INDEX (b);
+
+  if (index_b >= COMPOSE_SECOND_SINGLE_START)
+    {
+      if (a ==
+         compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][0])
+       {
+         *result =
+           compose_second_single[index_b - COMPOSE_SECOND_SINGLE_START][1];
+         return TRUE;
+       }
+      else
+       return FALSE;
+    }
+
+  if (index_a >= COMPOSE_FIRST_START && index_a < COMPOSE_FIRST_SINGLE_START
+      && index_b >= COMPOSE_SECOND_START
+      && index_b < COMPOSE_SECOND_SINGLE_START)
+    {
+      gunichar res =
+       compose_array[index_a - COMPOSE_FIRST_START][index_b -
+                                                    COMPOSE_SECOND_START];
+
+      if (res)
+       {
+         *result = res;
+         return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
+static gunichar *
+_g_utf8_normalize_wc (const gchar * str, gssize max_len, GNormalizeMode mode)
+{
+  gsize n_wc;
+  gunichar *wc_buffer;
+  const char *p;
+  gsize last_start;
+  gboolean do_compat = (mode == G_NORMALIZE_NFKC || mode == G_NORMALIZE_NFKD);
+  gboolean do_compose = (mode == G_NORMALIZE_NFC || mode == G_NORMALIZE_NFKC);
+
+  n_wc = 0;
+  p = str;
+  while ((max_len < 0 || p < str + max_len) && *p)
+    {
+      const gchar *decomp;
+      gunichar wc = g_utf8_get_char (p);
+
+      if (wc >= 0xac00 && wc <= 0xd7af)
+       {
+         gsize result_len;
+         decompose_hangul (wc, NULL, &result_len);
+         n_wc += result_len;
+       }
+      else
+       {
+         decomp = find_decomposition (wc, do_compat);
+
+         if (decomp)
+           n_wc += g_utf8_strlen (decomp, -1);
+         else
+           n_wc++;
+       }
+
+      p = g_utf8_next_char (p);
+    }
+
+  wc_buffer = g_new (gunichar, n_wc + 1);
+  if (!wc_buffer)
+    return NULL;
+
+  last_start = 0;
+  n_wc = 0;
+  p = str;
+  while ((max_len < 0 || p < str + max_len) && *p)
+    {
+      gunichar wc = g_utf8_get_char (p);
+      const gchar *decomp;
+      int cc;
+      gsize old_n_wc = n_wc;
+
+      if (wc >= 0xac00 && wc <= 0xd7af)
+       {
+         gsize result_len;
+         decompose_hangul (wc, wc_buffer + n_wc, &result_len);
+         n_wc += result_len;
+       }
+      else
+       {
+         decomp = find_decomposition (wc, do_compat);
+
+         if (decomp)
+           {
+             const char *pd;
+             for (pd = decomp; *pd != '\0'; pd = g_utf8_next_char (pd))
+               wc_buffer[n_wc++] = g_utf8_get_char (pd);
+           }
+         else
+           wc_buffer[n_wc++] = wc;
+       }
+
+      if (n_wc > 0)
+       {
+         cc = COMBINING_CLASS (wc_buffer[old_n_wc]);
+
+         if (cc == 0)
+           {
+             g_unicode_canonical_ordering (wc_buffer + last_start,
+                                           n_wc - last_start);
+             last_start = old_n_wc;
+           }
+       }
+
+      p = g_utf8_next_char (p);
+    }
+
+  if (n_wc > 0)
+    {
+      g_unicode_canonical_ordering (wc_buffer + last_start,
+                                   n_wc - last_start);
+      last_start = n_wc;
+    }
+
+  wc_buffer[n_wc] = 0;
+
+  /* All decomposed and reordered */
+
+  if (do_compose && n_wc > 0)
+    {
+      gsize i, j;
+      int last_cc = 0;
+      last_start = 0;
+
+      for (i = 0; i < n_wc; i++)
+       {
+         int cc = COMBINING_CLASS (wc_buffer[i]);
+
+         if (i > 0 &&
+             (last_cc == 0 || last_cc != cc) &&
+             combine (wc_buffer[last_start], wc_buffer[i],
+                      &wc_buffer[last_start]))
+           {
+             for (j = i + 1; j < n_wc; j++)
+               wc_buffer[j - 1] = wc_buffer[j];
+             n_wc--;
+             i--;
+
+             if (i == last_start)
+               last_cc = 0;
+             else
+               last_cc = COMBINING_CLASS (wc_buffer[i - 1]);
+
+             continue;
+           }
+
+         if (cc == 0)
+           last_start = i;
+
+         last_cc = cc;
+       }
+    }
+
+  wc_buffer[n_wc] = 0;
+
+  return wc_buffer;
+}
+
+/*
+ * g_utf8_normalize:
+ * @str: a UTF-8 encoded string.
+ * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
+ * @mode: the type of normalization to perform.
+ *
+ * Converts a string into canonical form, standardizing
+ * such issues as whether a character with an accent
+ * is represented as a base character and combining
+ * accent or as a single precomposed character. You
+ * should generally call g_utf8_normalize() before
+ * comparing two Unicode strings.
+ *
+ * The normalization mode %G_NORMALIZE_DEFAULT only
+ * standardizes differences that do not affect the
+ * text content, such as the above-mentioned accent
+ * representation. %G_NORMALIZE_ALL also standardizes
+ * the "compatibility" characters in Unicode, such
+ * as SUPERSCRIPT THREE to the standard forms
+ * (in this case DIGIT THREE). Formatting information
+ * may be lost but for most text operations such
+ * characters should be considered the same.
+ * For example, g_utf8_collate() normalizes
+ * with %G_NORMALIZE_ALL as its first step.
+ *
+ * %G_NORMALIZE_DEFAULT_COMPOSE and %G_NORMALIZE_ALL_COMPOSE
+ * are like %G_NORMALIZE_DEFAULT and %G_NORMALIZE_ALL,
+ * but returned a result with composed forms rather
+ * than a maximally decomposed form. This is often
+ * useful if you intend to convert the string to
+ * a legacy encoding or pass it to a system with
+ * less capable Unicode handling.
+ *
+ * Return value: a newly allocated string, that is the
+ *   normalized form of @str.
+ **/
+static gchar *
+g_utf8_normalize (const gchar * str, gssize len, GNormalizeMode mode)
+{
+  gunichar *result_wc = _g_utf8_normalize_wc (str, len, mode);
+  gchar *result;
+
+  result = g_ucs4_to_utf8 (result_wc, -1, NULL, NULL, NULL);
+  g_free (result_wc);
+
+  return result;
+}
+
+/* Public Libidn API starts here. */
+
+/**
+ * stringprep_utf8_to_unichar:
+ * @p: a pointer to Unicode character encoded as UTF-8
+ *
+ * Converts a sequence of bytes encoded as UTF-8 to a Unicode character.
+ * If @p does not point to a valid UTF-8 encoded character, results are
+ * undefined.
+ *
+ * Return value: the resulting character.
+ **/
+uint32_t
+stringprep_utf8_to_unichar (const char *p)
+{
+  return g_utf8_get_char (p);
+}
+
+/**
+ * stringprep_unichar_to_utf8:
+ * @c: a ISO10646 character code
+ * @outbuf: output buffer, must have at least 6 bytes of space.
+ *       If %NULL, the length will be computed and returned
+ *       and nothing will be written to @outbuf.
+ *
+ * Converts a single character to UTF-8.
+ *
+ * Return value: number of bytes written.
+ **/
+int
+stringprep_unichar_to_utf8 (uint32_t c, char *outbuf)
+{
+  return g_unichar_to_utf8 (c, outbuf);
+}
+
+/**
+ * stringprep_utf8_to_ucs4:
+ * @str: a UTF-8 encoded string
+ * @len: the maximum length of @str to use. If @len < 0, then
+ *       the string is nul-terminated.
+ * @items_written: location to store the number of characters in the
+ *                 result, or %NULL.
+ *
+ * Convert a string from UTF-8 to a 32-bit fixed width
+ * representation as UCS-4, assuming valid UTF-8 input.
+ * This function does no error checking on the input.
+ *
+ * Return value: a pointer to a newly allocated UCS-4 string.
+ *               This value must be freed with free().
+ **/
+uint32_t *
+stringprep_utf8_to_ucs4 (const char *str, ssize_t len, size_t * items_written)
+{
+  return g_utf8_to_ucs4_fast (str, (glong) len, (glong *) items_written);
+}
+
+/**
+ * stringprep_ucs4_to_utf8:
+ * @str: a UCS-4 encoded string
+ * @len: the maximum length of @str to use. If @len < 0, then
+ *       the string is terminated with a 0 character.
+ * @items_read: location to store number of characters read read, or %NULL.
+ * @items_written: location to store number of bytes written or %NULL.
+ *                 The value here stored does not include the trailing 0
+ *                 byte.
+ *
+ * Convert a string from a 32-bit fixed width representation as UCS-4.
+ * to UTF-8. The result will be terminated with a 0 byte.
+ *
+ * Return value: a pointer to a newly allocated UTF-8 string.
+ *               This value must be freed with free(). If an
+ *               error occurs, %NULL will be returned and
+ *               @error set.
+ **/
+char *
+stringprep_ucs4_to_utf8 (const uint32_t * str, ssize_t len,
+                        size_t * items_read, size_t * items_written)
+{
+  return g_ucs4_to_utf8 (str, len, (glong *) items_read,
+                        (glong *) items_written, NULL);
+}
+
+/**
+ * stringprep_utf8_nfkc_normalize:
+ * @str: a UTF-8 encoded string.
+ * @len: length of @str, in bytes, or -1 if @str is nul-terminated.
+ *
+ * Converts a string into canonical form, standardizing
+ * such issues as whether a character with an accent
+ * is represented as a base character and combining
+ * accent or as a single precomposed character.
+ *
+ * The normalization mode is NFKC (ALL COMPOSE).  It standardizes
+ * differences that do not affect the text content, such as the
+ * above-mentioned accent representation. It standardizes the
+ * "compatibility" characters in Unicode, such as SUPERSCRIPT THREE to
+ * the standard forms (in this case DIGIT THREE). Formatting
+ * information may be lost but for most text operations such
+ * characters should be considered the same. It returns a result with
+ * composed forms rather than a maximally decomposed form.
+ *
+ * Return value: a newly allocated string, that is the
+ *   NFKC normalized form of @str.
+ **/
+char *
+stringprep_utf8_nfkc_normalize (const char *str, ssize_t len)
+{
+  return g_utf8_normalize (str, len, G_NORMALIZE_NFKC);
+}
+
+/**
+ * stringprep_ucs4_nfkc_normalize:
+ * @str: a Unicode string.
+ * @len: length of @str array, or -1 if @str is nul-terminated.
+ *
+ * Converts UCS4 string into UTF-8 and runs
+ * stringprep_utf8_nfkc_normalize().
+ *
+ * Return value: a newly allocated Unicode string, that is the NFKC
+ *   normalized form of @str.
+ **/
+uint32_t *
+stringprep_ucs4_nfkc_normalize (uint32_t * str, ssize_t len)
+{
+  char *p;
+  uint32_t *result_wc;
+
+  p = stringprep_ucs4_to_utf8 (str, len, 0, 0);
+  result_wc = _g_utf8_normalize_wc (p, -1, G_NORMALIZE_NFKC);
+  free (p);
+
+  return result_wc;
+}
diff --git a/lib/contrib/rfc3454.c b/lib/contrib/rfc3454.c
new file mode 100644 (file)
index 0000000..99d1677
--- /dev/null
@@ -0,0 +1,3544 @@
+/* This file is automatically generated.  DO NOT EDIT!
+   Instead, edit gen-stringprep-tables.pl and re-run.  */
+
+#include "stringprep.h"
+
+/*
+ * A.1 Unassigned code points in Unicode 3.2
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_A_1[] = {
+  { 0x000221           },                                            /* 0221 */
+  { 0x000234, 0x00024F },                                       /* 0234-024F */
+  { 0x0002AE, 0x0002AF },                                       /* 02AE-02AF */
+  { 0x0002EF, 0x0002FF },                                       /* 02EF-02FF */
+  { 0x000350, 0x00035F },                                       /* 0350-035F */
+  { 0x000370, 0x000373 },                                       /* 0370-0373 */
+  { 0x000376, 0x000379 },                                       /* 0376-0379 */
+  { 0x00037B, 0x00037D },                                       /* 037B-037D */
+  { 0x00037F, 0x000383 },                                       /* 037F-0383 */
+  { 0x00038B           },                                            /* 038B */
+  { 0x00038D           },                                            /* 038D */
+  { 0x0003A2           },                                            /* 03A2 */
+  { 0x0003CF           },                                            /* 03CF */
+  { 0x0003F7, 0x0003FF },                                       /* 03F7-03FF */
+  { 0x000487           },                                            /* 0487 */
+  { 0x0004CF           },                                            /* 04CF */
+  { 0x0004F6, 0x0004F7 },                                       /* 04F6-04F7 */
+  { 0x0004FA, 0x0004FF },                                       /* 04FA-04FF */
+  { 0x000510, 0x000530 },                                       /* 0510-0530 */
+  { 0x000557, 0x000558 },                                       /* 0557-0558 */
+  { 0x000560           },                                            /* 0560 */
+  { 0x000588           },                                            /* 0588 */
+  { 0x00058B, 0x000590 },                                       /* 058B-0590 */
+  { 0x0005A2           },                                            /* 05A2 */
+  { 0x0005BA           },                                            /* 05BA */
+  { 0x0005C5, 0x0005CF },                                       /* 05C5-05CF */
+  { 0x0005EB, 0x0005EF },                                       /* 05EB-05EF */
+  { 0x0005F5, 0x00060B },                                       /* 05F5-060B */
+  { 0x00060D, 0x00061A },                                       /* 060D-061A */
+  { 0x00061C, 0x00061E },                                       /* 061C-061E */
+  { 0x000620           },                                            /* 0620 */
+  { 0x00063B, 0x00063F },                                       /* 063B-063F */
+  { 0x000656, 0x00065F },                                       /* 0656-065F */
+  { 0x0006EE, 0x0006EF },                                       /* 06EE-06EF */
+  { 0x0006FF           },                                            /* 06FF */
+  { 0x00070E           },                                            /* 070E */
+  { 0x00072D, 0x00072F },                                       /* 072D-072F */
+  { 0x00074B, 0x00077F },                                       /* 074B-077F */
+  { 0x0007B2, 0x000900 },                                       /* 07B2-0900 */
+  { 0x000904           },                                            /* 0904 */
+  { 0x00093A, 0x00093B },                                       /* 093A-093B */
+  { 0x00094E, 0x00094F },                                       /* 094E-094F */
+  { 0x000955, 0x000957 },                                       /* 0955-0957 */
+  { 0x000971, 0x000980 },                                       /* 0971-0980 */
+  { 0x000984           },                                            /* 0984 */
+  { 0x00098D, 0x00098E },                                       /* 098D-098E */
+  { 0x000991, 0x000992 },                                       /* 0991-0992 */
+  { 0x0009A9           },                                            /* 09A9 */
+  { 0x0009B1           },                                            /* 09B1 */
+  { 0x0009B3, 0x0009B5 },                                       /* 09B3-09B5 */
+  { 0x0009BA, 0x0009BB },                                       /* 09BA-09BB */
+  { 0x0009BD           },                                            /* 09BD */
+  { 0x0009C5, 0x0009C6 },                                       /* 09C5-09C6 */
+  { 0x0009C9, 0x0009CA },                                       /* 09C9-09CA */
+  { 0x0009CE, 0x0009D6 },                                       /* 09CE-09D6 */
+  { 0x0009D8, 0x0009DB },                                       /* 09D8-09DB */
+  { 0x0009DE           },                                            /* 09DE */
+  { 0x0009E4, 0x0009E5 },                                       /* 09E4-09E5 */
+  { 0x0009FB, 0x000A01 },                                       /* 09FB-0A01 */
+  { 0x000A03, 0x000A04 },                                       /* 0A03-0A04 */
+  { 0x000A0B, 0x000A0E },                                       /* 0A0B-0A0E */
+  { 0x000A11, 0x000A12 },                                       /* 0A11-0A12 */
+  { 0x000A29           },                                            /* 0A29 */
+  { 0x000A31           },                                            /* 0A31 */
+  { 0x000A34           },                                            /* 0A34 */
+  { 0x000A37           },                                            /* 0A37 */
+  { 0x000A3A, 0x000A3B },                                       /* 0A3A-0A3B */
+  { 0x000A3D           },                                            /* 0A3D */
+  { 0x000A43, 0x000A46 },                                       /* 0A43-0A46 */
+  { 0x000A49, 0x000A4A },                                       /* 0A49-0A4A */
+  { 0x000A4E, 0x000A58 },                                       /* 0A4E-0A58 */
+  { 0x000A5D           },                                            /* 0A5D */
+  { 0x000A5F, 0x000A65 },                                       /* 0A5F-0A65 */
+  { 0x000A75, 0x000A80 },                                       /* 0A75-0A80 */
+  { 0x000A84           },                                            /* 0A84 */
+  { 0x000A8C           },                                            /* 0A8C */
+  { 0x000A8E           },                                            /* 0A8E */
+  { 0x000A92           },                                            /* 0A92 */
+  { 0x000AA9           },                                            /* 0AA9 */
+  { 0x000AB1           },                                            /* 0AB1 */
+  { 0x000AB4           },                                            /* 0AB4 */
+  { 0x000ABA, 0x000ABB },                                       /* 0ABA-0ABB */
+  { 0x000AC6           },                                            /* 0AC6 */
+  { 0x000ACA           },                                            /* 0ACA */
+  { 0x000ACE, 0x000ACF },                                       /* 0ACE-0ACF */
+  { 0x000AD1, 0x000ADF },                                       /* 0AD1-0ADF */
+  { 0x000AE1, 0x000AE5 },                                       /* 0AE1-0AE5 */
+  { 0x000AF0, 0x000B00 },                                       /* 0AF0-0B00 */
+  { 0x000B04           },                                            /* 0B04 */
+  { 0x000B0D, 0x000B0E },                                       /* 0B0D-0B0E */
+  { 0x000B11, 0x000B12 },                                       /* 0B11-0B12 */
+  { 0x000B29           },                                            /* 0B29 */
+  { 0x000B31           },                                            /* 0B31 */
+  { 0x000B34, 0x000B35 },                                       /* 0B34-0B35 */
+  { 0x000B3A, 0x000B3B },                                       /* 0B3A-0B3B */
+  { 0x000B44, 0x000B46 },                                       /* 0B44-0B46 */
+  { 0x000B49, 0x000B4A },                                       /* 0B49-0B4A */
+  { 0x000B4E, 0x000B55 },                                       /* 0B4E-0B55 */
+  { 0x000B58, 0x000B5B },                                       /* 0B58-0B5B */
+  { 0x000B5E           },                                            /* 0B5E */
+  { 0x000B62, 0x000B65 },                                       /* 0B62-0B65 */
+  { 0x000B71, 0x000B81 },                                       /* 0B71-0B81 */
+  { 0x000B84           },                                            /* 0B84 */
+  { 0x000B8B, 0x000B8D },                                       /* 0B8B-0B8D */
+  { 0x000B91           },                                            /* 0B91 */
+  { 0x000B96, 0x000B98 },                                       /* 0B96-0B98 */
+  { 0x000B9B           },                                            /* 0B9B */
+  { 0x000B9D           },                                            /* 0B9D */
+  { 0x000BA0, 0x000BA2 },                                       /* 0BA0-0BA2 */
+  { 0x000BA5, 0x000BA7 },                                       /* 0BA5-0BA7 */
+  { 0x000BAB, 0x000BAD },                                       /* 0BAB-0BAD */
+  { 0x000BB6           },                                            /* 0BB6 */
+  { 0x000BBA, 0x000BBD },                                       /* 0BBA-0BBD */
+  { 0x000BC3, 0x000BC5 },                                       /* 0BC3-0BC5 */
+  { 0x000BC9           },                                            /* 0BC9 */
+  { 0x000BCE, 0x000BD6 },                                       /* 0BCE-0BD6 */
+  { 0x000BD8, 0x000BE6 },                                       /* 0BD8-0BE6 */
+  { 0x000BF3, 0x000C00 },                                       /* 0BF3-0C00 */
+  { 0x000C04           },                                            /* 0C04 */
+  { 0x000C0D           },                                            /* 0C0D */
+  { 0x000C11           },                                            /* 0C11 */
+  { 0x000C29           },                                            /* 0C29 */
+  { 0x000C34           },                                            /* 0C34 */
+  { 0x000C3A, 0x000C3D },                                       /* 0C3A-0C3D */
+  { 0x000C45           },                                            /* 0C45 */
+  { 0x000C49           },                                            /* 0C49 */
+  { 0x000C4E, 0x000C54 },                                       /* 0C4E-0C54 */
+  { 0x000C57, 0x000C5F },                                       /* 0C57-0C5F */
+  { 0x000C62, 0x000C65 },                                       /* 0C62-0C65 */
+  { 0x000C70, 0x000C81 },                                       /* 0C70-0C81 */
+  { 0x000C84           },                                            /* 0C84 */
+  { 0x000C8D           },                                            /* 0C8D */
+  { 0x000C91           },                                            /* 0C91 */
+  { 0x000CA9           },                                            /* 0CA9 */
+  { 0x000CB4           },                                            /* 0CB4 */
+  { 0x000CBA, 0x000CBD },                                       /* 0CBA-0CBD */
+  { 0x000CC5           },                                            /* 0CC5 */
+  { 0x000CC9           },                                            /* 0CC9 */
+  { 0x000CCE, 0x000CD4 },                                       /* 0CCE-0CD4 */
+  { 0x000CD7, 0x000CDD },                                       /* 0CD7-0CDD */
+  { 0x000CDF           },                                            /* 0CDF */
+  { 0x000CE2, 0x000CE5 },                                       /* 0CE2-0CE5 */
+  { 0x000CF0, 0x000D01 },                                       /* 0CF0-0D01 */
+  { 0x000D04           },                                            /* 0D04 */
+  { 0x000D0D           },                                            /* 0D0D */
+  { 0x000D11           },                                            /* 0D11 */
+  { 0x000D29           },                                            /* 0D29 */
+  { 0x000D3A, 0x000D3D },                                       /* 0D3A-0D3D */
+  { 0x000D44, 0x000D45 },                                       /* 0D44-0D45 */
+  { 0x000D49           },                                            /* 0D49 */
+  { 0x000D4E, 0x000D56 },                                       /* 0D4E-0D56 */
+  { 0x000D58, 0x000D5F },                                       /* 0D58-0D5F */
+  { 0x000D62, 0x000D65 },                                       /* 0D62-0D65 */
+  { 0x000D70, 0x000D81 },                                       /* 0D70-0D81 */
+  { 0x000D84           },                                            /* 0D84 */
+  { 0x000D97, 0x000D99 },                                       /* 0D97-0D99 */
+  { 0x000DB2           },                                            /* 0DB2 */
+  { 0x000DBC           },                                            /* 0DBC */
+  { 0x000DBE, 0x000DBF },                                       /* 0DBE-0DBF */
+  { 0x000DC7, 0x000DC9 },                                       /* 0DC7-0DC9 */
+  { 0x000DCB, 0x000DCE },                                       /* 0DCB-0DCE */
+  { 0x000DD5           },                                            /* 0DD5 */
+  { 0x000DD7           },                                            /* 0DD7 */
+  { 0x000DE0, 0x000DF1 },                                       /* 0DE0-0DF1 */
+  { 0x000DF5, 0x000E00 },                                       /* 0DF5-0E00 */
+  { 0x000E3B, 0x000E3E },                                       /* 0E3B-0E3E */
+  { 0x000E5C, 0x000E80 },                                       /* 0E5C-0E80 */
+  { 0x000E83           },                                            /* 0E83 */
+  { 0x000E85, 0x000E86 },                                       /* 0E85-0E86 */
+  { 0x000E89           },                                            /* 0E89 */
+  { 0x000E8B, 0x000E8C },                                       /* 0E8B-0E8C */
+  { 0x000E8E, 0x000E93 },                                       /* 0E8E-0E93 */
+  { 0x000E98           },                                            /* 0E98 */
+  { 0x000EA0           },                                            /* 0EA0 */
+  { 0x000EA4           },                                            /* 0EA4 */
+  { 0x000EA6           },                                            /* 0EA6 */
+  { 0x000EA8, 0x000EA9 },                                       /* 0EA8-0EA9 */
+  { 0x000EAC           },                                            /* 0EAC */
+  { 0x000EBA           },                                            /* 0EBA */
+  { 0x000EBE, 0x000EBF },                                       /* 0EBE-0EBF */
+  { 0x000EC5           },                                            /* 0EC5 */
+  { 0x000EC7           },                                            /* 0EC7 */
+  { 0x000ECE, 0x000ECF },                                       /* 0ECE-0ECF */
+  { 0x000EDA, 0x000EDB },                                       /* 0EDA-0EDB */
+  { 0x000EDE, 0x000EFF },                                       /* 0EDE-0EFF */
+  { 0x000F48           },                                            /* 0F48 */
+  { 0x000F6B, 0x000F70 },                                       /* 0F6B-0F70 */
+  { 0x000F8C, 0x000F8F },                                       /* 0F8C-0F8F */
+  { 0x000F98           },                                            /* 0F98 */
+  { 0x000FBD           },                                            /* 0FBD */
+  { 0x000FCD, 0x000FCE },                                       /* 0FCD-0FCE */
+  { 0x000FD0, 0x000FFF },                                       /* 0FD0-0FFF */
+  { 0x001022           },                                            /* 1022 */
+  { 0x001028           },                                            /* 1028 */
+  { 0x00102B           },                                            /* 102B */
+  { 0x001033, 0x001035 },                                       /* 1033-1035 */
+  { 0x00103A, 0x00103F },                                       /* 103A-103F */
+  { 0x00105A, 0x00109F },                                       /* 105A-109F */
+  { 0x0010C6, 0x0010CF },                                       /* 10C6-10CF */
+  { 0x0010F9, 0x0010FA },                                       /* 10F9-10FA */
+  { 0x0010FC, 0x0010FF },                                       /* 10FC-10FF */
+  { 0x00115A, 0x00115E },                                       /* 115A-115E */
+  { 0x0011A3, 0x0011A7 },                                       /* 11A3-11A7 */
+  { 0x0011FA, 0x0011FF },                                       /* 11FA-11FF */
+  { 0x001207           },                                            /* 1207 */
+  { 0x001247           },                                            /* 1247 */
+  { 0x001249           },                                            /* 1249 */
+  { 0x00124E, 0x00124F },                                       /* 124E-124F */
+  { 0x001257           },                                            /* 1257 */
+  { 0x001259           },                                            /* 1259 */
+  { 0x00125E, 0x00125F },                                       /* 125E-125F */
+  { 0x001287           },                                            /* 1287 */
+  { 0x001289           },                                            /* 1289 */
+  { 0x00128E, 0x00128F },                                       /* 128E-128F */
+  { 0x0012AF           },                                            /* 12AF */
+  { 0x0012B1           },                                            /* 12B1 */
+  { 0x0012B6, 0x0012B7 },                                       /* 12B6-12B7 */
+  { 0x0012BF           },                                            /* 12BF */
+  { 0x0012C1           },                                            /* 12C1 */
+  { 0x0012C6, 0x0012C7 },                                       /* 12C6-12C7 */
+  { 0x0012CF           },                                            /* 12CF */
+  { 0x0012D7           },                                            /* 12D7 */
+  { 0x0012EF           },                                            /* 12EF */
+  { 0x00130F           },                                            /* 130F */
+  { 0x001311           },                                            /* 1311 */
+  { 0x001316, 0x001317 },                                       /* 1316-1317 */
+  { 0x00131F           },                                            /* 131F */
+  { 0x001347           },                                            /* 1347 */
+  { 0x00135B, 0x001360 },                                       /* 135B-1360 */
+  { 0x00137D, 0x00139F },                                       /* 137D-139F */
+  { 0x0013F5, 0x001400 },                                       /* 13F5-1400 */
+  { 0x001677, 0x00167F },                                       /* 1677-167F */
+  { 0x00169D, 0x00169F },                                       /* 169D-169F */
+  { 0x0016F1, 0x0016FF },                                       /* 16F1-16FF */
+  { 0x00170D           },                                            /* 170D */
+  { 0x001715, 0x00171F },                                       /* 1715-171F */
+  { 0x001737, 0x00173F },                                       /* 1737-173F */
+  { 0x001754, 0x00175F },                                       /* 1754-175F */
+  { 0x00176D           },                                            /* 176D */
+  { 0x001771           },                                            /* 1771 */
+  { 0x001774, 0x00177F },                                       /* 1774-177F */
+  { 0x0017DD, 0x0017DF },                                       /* 17DD-17DF */
+  { 0x0017EA, 0x0017FF },                                       /* 17EA-17FF */
+  { 0x00180F           },                                            /* 180F */
+  { 0x00181A, 0x00181F },                                       /* 181A-181F */
+  { 0x001878, 0x00187F },                                       /* 1878-187F */
+  { 0x0018AA, 0x001DFF },                                       /* 18AA-1DFF */
+  { 0x001E9C, 0x001E9F },                                       /* 1E9C-1E9F */
+  { 0x001EFA, 0x001EFF },                                       /* 1EFA-1EFF */
+  { 0x001F16, 0x001F17 },                                       /* 1F16-1F17 */
+  { 0x001F1E, 0x001F1F },                                       /* 1F1E-1F1F */
+  { 0x001F46, 0x001F47 },                                       /* 1F46-1F47 */
+  { 0x001F4E, 0x001F4F },                                       /* 1F4E-1F4F */
+  { 0x001F58           },                                            /* 1F58 */
+  { 0x001F5A           },                                            /* 1F5A */
+  { 0x001F5C           },                                            /* 1F5C */
+  { 0x001F5E           },                                            /* 1F5E */
+  { 0x001F7E, 0x001F7F },                                       /* 1F7E-1F7F */
+  { 0x001FB5           },                                            /* 1FB5 */
+  { 0x001FC5           },                                            /* 1FC5 */
+  { 0x001FD4, 0x001FD5 },                                       /* 1FD4-1FD5 */
+  { 0x001FDC           },                                            /* 1FDC */
+  { 0x001FF0, 0x001FF1 },                                       /* 1FF0-1FF1 */
+  { 0x001FF5           },                                            /* 1FF5 */
+  { 0x001FFF           },                                            /* 1FFF */
+  { 0x002053, 0x002056 },                                       /* 2053-2056 */
+  { 0x002058, 0x00205E },                                       /* 2058-205E */
+  { 0x002064, 0x002069 },                                       /* 2064-2069 */
+  { 0x002072, 0x002073 },                                       /* 2072-2073 */
+  { 0x00208F, 0x00209F },                                       /* 208F-209F */
+  { 0x0020B2, 0x0020CF },                                       /* 20B2-20CF */
+  { 0x0020EB, 0x0020FF },                                       /* 20EB-20FF */
+  { 0x00213B, 0x00213C },                                       /* 213B-213C */
+  { 0x00214C, 0x002152 },                                       /* 214C-2152 */
+  { 0x002184, 0x00218F },                                       /* 2184-218F */
+  { 0x0023CF, 0x0023FF },                                       /* 23CF-23FF */
+  { 0x002427, 0x00243F },                                       /* 2427-243F */
+  { 0x00244B, 0x00245F },                                       /* 244B-245F */
+  { 0x0024FF           },                                            /* 24FF */
+  { 0x002614, 0x002615 },                                       /* 2614-2615 */
+  { 0x002618           },                                            /* 2618 */
+  { 0x00267E, 0x00267F },                                       /* 267E-267F */
+  { 0x00268A, 0x002700 },                                       /* 268A-2700 */
+  { 0x002705           },                                            /* 2705 */
+  { 0x00270A, 0x00270B },                                       /* 270A-270B */
+  { 0x002728           },                                            /* 2728 */
+  { 0x00274C           },                                            /* 274C */
+  { 0x00274E           },                                            /* 274E */
+  { 0x002753, 0x002755 },                                       /* 2753-2755 */
+  { 0x002757           },                                            /* 2757 */
+  { 0x00275F, 0x002760 },                                       /* 275F-2760 */
+  { 0x002795, 0x002797 },                                       /* 2795-2797 */
+  { 0x0027B0           },                                            /* 27B0 */
+  { 0x0027BF, 0x0027CF },                                       /* 27BF-27CF */
+  { 0x0027EC, 0x0027EF },                                       /* 27EC-27EF */
+  { 0x002B00, 0x002E7F },                                       /* 2B00-2E7F */
+  { 0x002E9A           },                                            /* 2E9A */
+  { 0x002EF4, 0x002EFF },                                       /* 2EF4-2EFF */
+  { 0x002FD6, 0x002FEF },                                       /* 2FD6-2FEF */
+  { 0x002FFC, 0x002FFF },                                       /* 2FFC-2FFF */
+  { 0x003040           },                                            /* 3040 */
+  { 0x003097, 0x003098 },                                       /* 3097-3098 */
+  { 0x003100, 0x003104 },                                       /* 3100-3104 */
+  { 0x00312D, 0x003130 },                                       /* 312D-3130 */
+  { 0x00318F           },                                            /* 318F */
+  { 0x0031B8, 0x0031EF },                                       /* 31B8-31EF */
+  { 0x00321D, 0x00321F },                                       /* 321D-321F */
+  { 0x003244, 0x003250 },                                       /* 3244-3250 */
+  { 0x00327C, 0x00327E },                                       /* 327C-327E */
+  { 0x0032CC, 0x0032CF },                                       /* 32CC-32CF */
+  { 0x0032FF           },                                            /* 32FF */
+  { 0x003377, 0x00337A },                                       /* 3377-337A */
+  { 0x0033DE, 0x0033DF },                                       /* 33DE-33DF */
+  { 0x0033FF           },                                            /* 33FF */
+  { 0x004DB6, 0x004DFF },                                       /* 4DB6-4DFF */
+  { 0x009FA6, 0x009FFF },                                       /* 9FA6-9FFF */
+  { 0x00A48D, 0x00A48F },                                       /* A48D-A48F */
+  { 0x00A4C7, 0x00ABFF },                                       /* A4C7-ABFF */
+  { 0x00D7A4, 0x00D7FF },                                       /* D7A4-D7FF */
+  { 0x00FA2E, 0x00FA2F },                                       /* FA2E-FA2F */
+  { 0x00FA6B, 0x00FAFF },                                       /* FA6B-FAFF */
+  { 0x00FB07, 0x00FB12 },                                       /* FB07-FB12 */
+  { 0x00FB18, 0x00FB1C },                                       /* FB18-FB1C */
+  { 0x00FB37           },                                            /* FB37 */
+  { 0x00FB3D           },                                            /* FB3D */
+  { 0x00FB3F           },                                            /* FB3F */
+  { 0x00FB42           },                                            /* FB42 */
+  { 0x00FB45           },                                            /* FB45 */
+  { 0x00FBB2, 0x00FBD2 },                                       /* FBB2-FBD2 */
+  { 0x00FD40, 0x00FD4F },                                       /* FD40-FD4F */
+  { 0x00FD90, 0x00FD91 },                                       /* FD90-FD91 */
+  { 0x00FDC8, 0x00FDCF },                                       /* FDC8-FDCF */
+  { 0x00FDFD, 0x00FDFF },                                       /* FDFD-FDFF */
+  { 0x00FE10, 0x00FE1F },                                       /* FE10-FE1F */
+  { 0x00FE24, 0x00FE2F },                                       /* FE24-FE2F */
+  { 0x00FE47, 0x00FE48 },                                       /* FE47-FE48 */
+  { 0x00FE53           },                                            /* FE53 */
+  { 0x00FE67           },                                            /* FE67 */
+  { 0x00FE6C, 0x00FE6F },                                       /* FE6C-FE6F */
+  { 0x00FE75           },                                            /* FE75 */
+  { 0x00FEFD, 0x00FEFE },                                       /* FEFD-FEFE */
+  { 0x00FF00           },                                            /* FF00 */
+  { 0x00FFBF, 0x00FFC1 },                                       /* FFBF-FFC1 */
+  { 0x00FFC8, 0x00FFC9 },                                       /* FFC8-FFC9 */
+  { 0x00FFD0, 0x00FFD1 },                                       /* FFD0-FFD1 */
+  { 0x00FFD8, 0x00FFD9 },                                       /* FFD8-FFD9 */
+  { 0x00FFDD, 0x00FFDF },                                       /* FFDD-FFDF */
+  { 0x00FFE7           },                                            /* FFE7 */
+  { 0x00FFEF, 0x00FFF8 },                                       /* FFEF-FFF8 */
+  { 0x010000, 0x0102FF },                                     /* 10000-102FF */
+  { 0x01031F           },                                           /* 1031F */
+  { 0x010324, 0x01032F },                                     /* 10324-1032F */
+  { 0x01034B, 0x0103FF },                                     /* 1034B-103FF */
+  { 0x010426, 0x010427 },                                     /* 10426-10427 */
+  { 0x01044E, 0x01CFFF },                                     /* 1044E-1CFFF */
+  { 0x01D0F6, 0x01D0FF },                                     /* 1D0F6-1D0FF */
+  { 0x01D127, 0x01D129 },                                     /* 1D127-1D129 */
+  { 0x01D1DE, 0x01D3FF },                                     /* 1D1DE-1D3FF */
+  { 0x01D455           },                                           /* 1D455 */
+  { 0x01D49D           },                                           /* 1D49D */
+  { 0x01D4A0, 0x01D4A1 },                                     /* 1D4A0-1D4A1 */
+  { 0x01D4A3, 0x01D4A4 },                                     /* 1D4A3-1D4A4 */
+  { 0x01D4A7, 0x01D4A8 },                                     /* 1D4A7-1D4A8 */
+  { 0x01D4AD           },                                           /* 1D4AD */
+  { 0x01D4BA           },                                           /* 1D4BA */
+  { 0x01D4BC           },                                           /* 1D4BC */
+  { 0x01D4C1           },                                           /* 1D4C1 */
+  { 0x01D4C4           },                                           /* 1D4C4 */
+  { 0x01D506           },                                           /* 1D506 */
+  { 0x01D50B, 0x01D50C },                                     /* 1D50B-1D50C */
+  { 0x01D515           },                                           /* 1D515 */
+  { 0x01D51D           },                                           /* 1D51D */
+  { 0x01D53A           },                                           /* 1D53A */
+  { 0x01D53F           },                                           /* 1D53F */
+  { 0x01D545           },                                           /* 1D545 */
+  { 0x01D547, 0x01D549 },                                     /* 1D547-1D549 */
+  { 0x01D551           },                                           /* 1D551 */
+  { 0x01D6A4, 0x01D6A7 },                                     /* 1D6A4-1D6A7 */
+  { 0x01D7CA, 0x01D7CD },                                     /* 1D7CA-1D7CD */
+  { 0x01D800, 0x01FFFD },                                     /* 1D800-1FFFD */
+  { 0x02A6D7, 0x02F7FF },                                     /* 2A6D7-2F7FF */
+  { 0x02FA1E, 0x02FFFD },                                     /* 2FA1E-2FFFD */
+  { 0x030000, 0x03FFFD },                                     /* 30000-3FFFD */
+  { 0x040000, 0x04FFFD },                                     /* 40000-4FFFD */
+  { 0x050000, 0x05FFFD },                                     /* 50000-5FFFD */
+  { 0x060000, 0x06FFFD },                                     /* 60000-6FFFD */
+  { 0x070000, 0x07FFFD },                                     /* 70000-7FFFD */
+  { 0x080000, 0x08FFFD },                                     /* 80000-8FFFD */
+  { 0x090000, 0x09FFFD },                                     /* 90000-9FFFD */
+  { 0x0A0000, 0x0AFFFD },                                     /* A0000-AFFFD */
+  { 0x0B0000, 0x0BFFFD },                                     /* B0000-BFFFD */
+  { 0x0C0000, 0x0CFFFD },                                     /* C0000-CFFFD */
+  { 0x0D0000, 0x0DFFFD },                                     /* D0000-DFFFD */
+  { 0x0E0000           },                                           /* E0000 */
+  { 0x0E0002, 0x0E001F },                                     /* E0002-E001F */
+  { 0x0E0080, 0x0EFFFD },                                     /* E0080-EFFFD */
+  { 0 },
+};
+
+
+/*
+ * B.1 Commonly mapped to nothing
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_B_1[] = {
+  { 0x0000AD           },                          /* 00AD; ; Map to nothing */
+  { 0x00034F           },                          /* 034F; ; Map to nothing */
+  { 0x001806           },                          /* 1806; ; Map to nothing */
+  { 0x00180B           },                          /* 180B; ; Map to nothing */
+  { 0x00180C           },                          /* 180C; ; Map to nothing */
+  { 0x00180D           },                          /* 180D; ; Map to nothing */
+  { 0x00200B           },                          /* 200B; ; Map to nothing */
+  { 0x00200C           },                          /* 200C; ; Map to nothing */
+  { 0x00200D           },                          /* 200D; ; Map to nothing */
+  { 0x002060           },                          /* 2060; ; Map to nothing */
+  { 0x00FE00           },                          /* FE00; ; Map to nothing */
+  { 0x00FE01           },                          /* FE01; ; Map to nothing */
+  { 0x00FE02           },                          /* FE02; ; Map to nothing */
+  { 0x00FE03           },                          /* FE03; ; Map to nothing */
+  { 0x00FE04           },                          /* FE04; ; Map to nothing */
+  { 0x00FE05           },                          /* FE05; ; Map to nothing */
+  { 0x00FE06           },                          /* FE06; ; Map to nothing */
+  { 0x00FE07           },                          /* FE07; ; Map to nothing */
+  { 0x00FE08           },                          /* FE08; ; Map to nothing */
+  { 0x00FE09           },                          /* FE09; ; Map to nothing */
+  { 0x00FE0A           },                          /* FE0A; ; Map to nothing */
+  { 0x00FE0B           },                          /* FE0B; ; Map to nothing */
+  { 0x00FE0C           },                          /* FE0C; ; Map to nothing */
+  { 0x00FE0D           },                          /* FE0D; ; Map to nothing */
+  { 0x00FE0E           },                          /* FE0E; ; Map to nothing */
+  { 0x00FE0F           },                          /* FE0F; ; Map to nothing */
+  { 0x00FEFF           },                          /* FEFF; ; Map to nothing */
+  { 0 },
+};
+
+
+/*
+ * B.2 Mapping for case-folding used with NFKC
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_B_2[] = {
+  { 0x000041, 0, { 0x000061 }},                      /* 0041; 0061; Case map */
+  { 0x000042, 0, { 0x000062 }},                      /* 0042; 0062; Case map */
+  { 0x000043, 0, { 0x000063 }},                      /* 0043; 0063; Case map */
+  { 0x000044, 0, { 0x000064 }},                      /* 0044; 0064; Case map */
+  { 0x000045, 0, { 0x000065 }},                      /* 0045; 0065; Case map */
+  { 0x000046, 0, { 0x000066 }},                      /* 0046; 0066; Case map */
+  { 0x000047, 0, { 0x000067 }},                      /* 0047; 0067; Case map */
+  { 0x000048, 0, { 0x000068 }},                      /* 0048; 0068; Case map */
+  { 0x000049, 0, { 0x000069 }},                      /* 0049; 0069; Case map */
+  { 0x00004A, 0, { 0x00006A }},                      /* 004A; 006A; Case map */
+  { 0x00004B, 0, { 0x00006B }},                      /* 004B; 006B; Case map */
+  { 0x00004C, 0, { 0x00006C }},                      /* 004C; 006C; Case map */
+  { 0x00004D, 0, { 0x00006D }},                      /* 004D; 006D; Case map */
+  { 0x00004E, 0, { 0x00006E }},                      /* 004E; 006E; Case map */
+  { 0x00004F, 0, { 0x00006F }},                      /* 004F; 006F; Case map */
+  { 0x000050, 0, { 0x000070 }},                      /* 0050; 0070; Case map */
+  { 0x000051, 0, { 0x000071 }},                      /* 0051; 0071; Case map */
+  { 0x000052, 0, { 0x000072 }},                      /* 0052; 0072; Case map */
+  { 0x000053, 0, { 0x000073 }},                      /* 0053; 0073; Case map */
+  { 0x000054, 0, { 0x000074 }},                      /* 0054; 0074; Case map */
+  { 0x000055, 0, { 0x000075 }},                      /* 0055; 0075; Case map */
+  { 0x000056, 0, { 0x000076 }},                      /* 0056; 0076; Case map */
+  { 0x000057, 0, { 0x000077 }},                      /* 0057; 0077; Case map */
+  { 0x000058, 0, { 0x000078 }},                      /* 0058; 0078; Case map */
+  { 0x000059, 0, { 0x000079 }},                      /* 0059; 0079; Case map */
+  { 0x00005A, 0, { 0x00007A }},                      /* 005A; 007A; Case map */
+  { 0x0000B5, 0, { 0x0003BC }},                      /* 00B5; 03BC; Case map */
+  { 0x0000C0, 0, { 0x0000E0 }},                      /* 00C0; 00E0; Case map */
+  { 0x0000C1, 0, { 0x0000E1 }},                      /* 00C1; 00E1; Case map */
+  { 0x0000C2, 0, { 0x0000E2 }},                      /* 00C2; 00E2; Case map */
+  { 0x0000C3, 0, { 0x0000E3 }},                      /* 00C3; 00E3; Case map */
+  { 0x0000C4, 0, { 0x0000E4 }},                      /* 00C4; 00E4; Case map */
+  { 0x0000C5, 0, { 0x0000E5 }},                      /* 00C5; 00E5; Case map */
+  { 0x0000C6, 0, { 0x0000E6 }},                      /* 00C6; 00E6; Case map */
+  { 0x0000C7, 0, { 0x0000E7 }},                      /* 00C7; 00E7; Case map */
+  { 0x0000C8, 0, { 0x0000E8 }},                      /* 00C8; 00E8; Case map */
+  { 0x0000C9, 0, { 0x0000E9 }},                      /* 00C9; 00E9; Case map */
+  { 0x0000CA, 0, { 0x0000EA }},                      /* 00CA; 00EA; Case map */
+  { 0x0000CB, 0, { 0x0000EB }},                      /* 00CB; 00EB; Case map */
+  { 0x0000CC, 0, { 0x0000EC }},                      /* 00CC; 00EC; Case map */
+  { 0x0000CD, 0, { 0x0000ED }},                      /* 00CD; 00ED; Case map */
+  { 0x0000CE, 0, { 0x0000EE }},                      /* 00CE; 00EE; Case map */
+  { 0x0000CF, 0, { 0x0000EF }},                      /* 00CF; 00EF; Case map */
+  { 0x0000D0, 0, { 0x0000F0 }},                      /* 00D0; 00F0; Case map */
+  { 0x0000D1, 0, { 0x0000F1 }},                      /* 00D1; 00F1; Case map */
+  { 0x0000D2, 0, { 0x0000F2 }},                      /* 00D2; 00F2; Case map */
+  { 0x0000D3, 0, { 0x0000F3 }},                      /* 00D3; 00F3; Case map */
+  { 0x0000D4, 0, { 0x0000F4 }},                      /* 00D4; 00F4; Case map */
+  { 0x0000D5, 0, { 0x0000F5 }},                      /* 00D5; 00F5; Case map */
+  { 0x0000D6, 0, { 0x0000F6 }},                      /* 00D6; 00F6; Case map */
+  { 0x0000D8, 0, { 0x0000F8 }},                      /* 00D8; 00F8; Case map */
+  { 0x0000D9, 0, { 0x0000F9 }},                      /* 00D9; 00F9; Case map */
+  { 0x0000DA, 0, { 0x0000FA }},                      /* 00DA; 00FA; Case map */
+  { 0x0000DB, 0, { 0x0000FB }},                      /* 00DB; 00FB; Case map */
+  { 0x0000DC, 0, { 0x0000FC }},                      /* 00DC; 00FC; Case map */
+  { 0x0000DD, 0, { 0x0000FD }},                      /* 00DD; 00FD; Case map */
+  { 0x0000DE, 0, { 0x0000FE }},                      /* 00DE; 00FE; Case map */
+  { 0x0000DF, 0, { 0x000073,                    /* 00DF; 0073 0073; Case map */
+                   0x000073 }},
+  { 0x000100, 0, { 0x000101 }},                      /* 0100; 0101; Case map */
+  { 0x000102, 0, { 0x000103 }},                      /* 0102; 0103; Case map */
+  { 0x000104, 0, { 0x000105 }},                      /* 0104; 0105; Case map */
+  { 0x000106, 0, { 0x000107 }},                      /* 0106; 0107; Case map */
+  { 0x000108, 0, { 0x000109 }},                      /* 0108; 0109; Case map */
+  { 0x00010A, 0, { 0x00010B }},                      /* 010A; 010B; Case map */
+  { 0x00010C, 0, { 0x00010D }},                      /* 010C; 010D; Case map */
+  { 0x00010E, 0, { 0x00010F }},                      /* 010E; 010F; Case map */
+  { 0x000110, 0, { 0x000111 }},                      /* 0110; 0111; Case map */
+  { 0x000112, 0, { 0x000113 }},                      /* 0112; 0113; Case map */
+  { 0x000114, 0, { 0x000115 }},                      /* 0114; 0115; Case map */
+  { 0x000116, 0, { 0x000117 }},                      /* 0116; 0117; Case map */
+  { 0x000118, 0, { 0x000119 }},                      /* 0118; 0119; Case map */
+  { 0x00011A, 0, { 0x00011B }},                      /* 011A; 011B; Case map */
+  { 0x00011C, 0, { 0x00011D }},                      /* 011C; 011D; Case map */
+  { 0x00011E, 0, { 0x00011F }},                      /* 011E; 011F; Case map */
+  { 0x000120, 0, { 0x000121 }},                      /* 0120; 0121; Case map */
+  { 0x000122, 0, { 0x000123 }},                      /* 0122; 0123; Case map */
+  { 0x000124, 0, { 0x000125 }},                      /* 0124; 0125; Case map */
+  { 0x000126, 0, { 0x000127 }},                      /* 0126; 0127; Case map */
+  { 0x000128, 0, { 0x000129 }},                      /* 0128; 0129; Case map */
+  { 0x00012A, 0, { 0x00012B }},                      /* 012A; 012B; Case map */
+  { 0x00012C, 0, { 0x00012D }},                      /* 012C; 012D; Case map */
+  { 0x00012E, 0, { 0x00012F }},                      /* 012E; 012F; Case map */
+  { 0x000130, 0, { 0x000069,                    /* 0130; 0069 0307; Case map */
+                   0x000307 }},
+  { 0x000132, 0, { 0x000133 }},                      /* 0132; 0133; Case map */
+  { 0x000134, 0, { 0x000135 }},                      /* 0134; 0135; Case map */
+  { 0x000136, 0, { 0x000137 }},                      /* 0136; 0137; Case map */
+  { 0x000139, 0, { 0x00013A }},                      /* 0139; 013A; Case map */
+  { 0x00013B, 0, { 0x00013C }},                      /* 013B; 013C; Case map */
+  { 0x00013D, 0, { 0x00013E }},                      /* 013D; 013E; Case map */
+  { 0x00013F, 0, { 0x000140 }},                      /* 013F; 0140; Case map */
+  { 0x000141, 0, { 0x000142 }},                      /* 0141; 0142; Case map */
+  { 0x000143, 0, { 0x000144 }},                      /* 0143; 0144; Case map */
+  { 0x000145, 0, { 0x000146 }},                      /* 0145; 0146; Case map */
+  { 0x000147, 0, { 0x000148 }},                      /* 0147; 0148; Case map */
+  { 0x000149, 0, { 0x0002BC,                    /* 0149; 02BC 006E; Case map */
+                   0x00006E }},
+  { 0x00014A, 0, { 0x00014B }},                      /* 014A; 014B; Case map */
+  { 0x00014C, 0, { 0x00014D }},                      /* 014C; 014D; Case map */
+  { 0x00014E, 0, { 0x00014F }},                      /* 014E; 014F; Case map */
+  { 0x000150, 0, { 0x000151 }},                      /* 0150; 0151; Case map */
+  { 0x000152, 0, { 0x000153 }},                      /* 0152; 0153; Case map */
+  { 0x000154, 0, { 0x000155 }},                      /* 0154; 0155; Case map */
+  { 0x000156, 0, { 0x000157 }},                      /* 0156; 0157; Case map */
+  { 0x000158, 0, { 0x000159 }},                      /* 0158; 0159; Case map */
+  { 0x00015A, 0, { 0x00015B }},                      /* 015A; 015B; Case map */
+  { 0x00015C, 0, { 0x00015D }},                      /* 015C; 015D; Case map */
+  { 0x00015E, 0, { 0x00015F }},                      /* 015E; 015F; Case map */
+  { 0x000160, 0, { 0x000161 }},                      /* 0160; 0161; Case map */
+  { 0x000162, 0, { 0x000163 }},                      /* 0162; 0163; Case map */
+  { 0x000164, 0, { 0x000165 }},                      /* 0164; 0165; Case map */
+  { 0x000166, 0, { 0x000167 }},                      /* 0166; 0167; Case map */
+  { 0x000168, 0, { 0x000169 }},                      /* 0168; 0169; Case map */
+  { 0x00016A, 0, { 0x00016B }},                      /* 016A; 016B; Case map */
+  { 0x00016C, 0, { 0x00016D }},                      /* 016C; 016D; Case map */
+  { 0x00016E, 0, { 0x00016F }},                      /* 016E; 016F; Case map */
+  { 0x000170, 0, { 0x000171 }},                      /* 0170; 0171; Case map */
+  { 0x000172, 0, { 0x000173 }},                      /* 0172; 0173; Case map */
+  { 0x000174, 0, { 0x000175 }},                      /* 0174; 0175; Case map */
+  { 0x000176, 0, { 0x000177 }},                      /* 0176; 0177; Case map */
+  { 0x000178, 0, { 0x0000FF }},                      /* 0178; 00FF; Case map */
+  { 0x000179, 0, { 0x00017A }},                      /* 0179; 017A; Case map */
+  { 0x00017B, 0, { 0x00017C }},                      /* 017B; 017C; Case map */
+  { 0x00017D, 0, { 0x00017E }},                      /* 017D; 017E; Case map */
+  { 0x00017F, 0, { 0x000073 }},                      /* 017F; 0073; Case map */
+  { 0x000181, 0, { 0x000253 }},                      /* 0181; 0253; Case map */
+  { 0x000182, 0, { 0x000183 }},                      /* 0182; 0183; Case map */
+  { 0x000184, 0, { 0x000185 }},                      /* 0184; 0185; Case map */
+  { 0x000186, 0, { 0x000254 }},                      /* 0186; 0254; Case map */
+  { 0x000187, 0, { 0x000188 }},                      /* 0187; 0188; Case map */
+  { 0x000189, 0, { 0x000256 }},                      /* 0189; 0256; Case map */
+  { 0x00018A, 0, { 0x000257 }},                      /* 018A; 0257; Case map */
+  { 0x00018B, 0, { 0x00018C }},                      /* 018B; 018C; Case map */
+  { 0x00018E, 0, { 0x0001DD }},                      /* 018E; 01DD; Case map */
+  { 0x00018F, 0, { 0x000259 }},                      /* 018F; 0259; Case map */
+  { 0x000190, 0, { 0x00025B }},                      /* 0190; 025B; Case map */
+  { 0x000191, 0, { 0x000192 }},                      /* 0191; 0192; Case map */
+  { 0x000193, 0, { 0x000260 }},                      /* 0193; 0260; Case map */
+  { 0x000194, 0, { 0x000263 }},                      /* 0194; 0263; Case map */
+  { 0x000196, 0, { 0x000269 }},                      /* 0196; 0269; Case map */
+  { 0x000197, 0, { 0x000268 }},                      /* 0197; 0268; Case map */
+  { 0x000198, 0, { 0x000199 }},                      /* 0198; 0199; Case map */
+  { 0x00019C, 0, { 0x00026F }},                      /* 019C; 026F; Case map */
+  { 0x00019D, 0, { 0x000272 }},                      /* 019D; 0272; Case map */
+  { 0x00019F, 0, { 0x000275 }},                      /* 019F; 0275; Case map */
+  { 0x0001A0, 0, { 0x0001A1 }},                      /* 01A0; 01A1; Case map */
+  { 0x0001A2, 0, { 0x0001A3 }},                      /* 01A2; 01A3; Case map */
+  { 0x0001A4, 0, { 0x0001A5 }},                      /* 01A4; 01A5; Case map */
+  { 0x0001A6, 0, { 0x000280 }},                      /* 01A6; 0280; Case map */
+  { 0x0001A7, 0, { 0x0001A8 }},                      /* 01A7; 01A8; Case map */
+  { 0x0001A9, 0, { 0x000283 }},                      /* 01A9; 0283; Case map */
+  { 0x0001AC, 0, { 0x0001AD }},                      /* 01AC; 01AD; Case map */
+  { 0x0001AE, 0, { 0x000288 }},                      /* 01AE; 0288; Case map */
+  { 0x0001AF, 0, { 0x0001B0 }},                      /* 01AF; 01B0; Case map */
+  { 0x0001B1, 0, { 0x00028A }},                      /* 01B1; 028A; Case map */
+  { 0x0001B2, 0, { 0x00028B }},                      /* 01B2; 028B; Case map */
+  { 0x0001B3, 0, { 0x0001B4 }},                      /* 01B3; 01B4; Case map */
+  { 0x0001B5, 0, { 0x0001B6 }},                      /* 01B5; 01B6; Case map */
+  { 0x0001B7, 0, { 0x000292 }},                      /* 01B7; 0292; Case map */
+  { 0x0001B8, 0, { 0x0001B9 }},                      /* 01B8; 01B9; Case map */
+  { 0x0001BC, 0, { 0x0001BD }},                      /* 01BC; 01BD; Case map */
+  { 0x0001C4, 0, { 0x0001C6 }},                      /* 01C4; 01C6; Case map */
+  { 0x0001C5, 0, { 0x0001C6 }},                      /* 01C5; 01C6; Case map */
+  { 0x0001C7, 0, { 0x0001C9 }},                      /* 01C7; 01C9; Case map */
+  { 0x0001C8, 0, { 0x0001C9 }},                      /* 01C8; 01C9; Case map */
+  { 0x0001CA, 0, { 0x0001CC }},                      /* 01CA; 01CC; Case map */
+  { 0x0001CB, 0, { 0x0001CC }},                      /* 01CB; 01CC; Case map */
+  { 0x0001CD, 0, { 0x0001CE }},                      /* 01CD; 01CE; Case map */
+  { 0x0001CF, 0, { 0x0001D0 }},                      /* 01CF; 01D0; Case map */
+  { 0x0001D1, 0, { 0x0001D2 }},                      /* 01D1; 01D2; Case map */
+  { 0x0001D3, 0, { 0x0001D4 }},                      /* 01D3; 01D4; Case map */
+  { 0x0001D5, 0, { 0x0001D6 }},                      /* 01D5; 01D6; Case map */
+  { 0x0001D7, 0, { 0x0001D8 }},                      /* 01D7; 01D8; Case map */
+  { 0x0001D9, 0, { 0x0001DA }},                      /* 01D9; 01DA; Case map */
+  { 0x0001DB, 0, { 0x0001DC }},                      /* 01DB; 01DC; Case map */
+  { 0x0001DE, 0, { 0x0001DF }},                      /* 01DE; 01DF; Case map */
+  { 0x0001E0, 0, { 0x0001E1 }},                      /* 01E0; 01E1; Case map */
+  { 0x0001E2, 0, { 0x0001E3 }},                      /* 01E2; 01E3; Case map */
+  { 0x0001E4, 0, { 0x0001E5 }},                      /* 01E4; 01E5; Case map */
+  { 0x0001E6, 0, { 0x0001E7 }},                      /* 01E6; 01E7; Case map */
+  { 0x0001E8, 0, { 0x0001E9 }},                      /* 01E8; 01E9; Case map */
+  { 0x0001EA, 0, { 0x0001EB }},                      /* 01EA; 01EB; Case map */
+  { 0x0001EC, 0, { 0x0001ED }},                      /* 01EC; 01ED; Case map */
+  { 0x0001EE, 0, { 0x0001EF }},                      /* 01EE; 01EF; Case map */
+  { 0x0001F0, 0, { 0x00006A,                    /* 01F0; 006A 030C; Case map */
+                   0x00030C }},
+  { 0x0001F1, 0, { 0x0001F3 }},                      /* 01F1; 01F3; Case map */
+  { 0x0001F2, 0, { 0x0001F3 }},                      /* 01F2; 01F3; Case map */
+  { 0x0001F4, 0, { 0x0001F5 }},                      /* 01F4; 01F5; Case map */
+  { 0x0001F6, 0, { 0x000195 }},                      /* 01F6; 0195; Case map */
+  { 0x0001F7, 0, { 0x0001BF }},                      /* 01F7; 01BF; Case map */
+  { 0x0001F8, 0, { 0x0001F9 }},                      /* 01F8; 01F9; Case map */
+  { 0x0001FA, 0, { 0x0001FB }},                      /* 01FA; 01FB; Case map */
+  { 0x0001FC, 0, { 0x0001FD }},                      /* 01FC; 01FD; Case map */
+  { 0x0001FE, 0, { 0x0001FF }},                      /* 01FE; 01FF; Case map */
+  { 0x000200, 0, { 0x000201 }},                      /* 0200; 0201; Case map */
+  { 0x000202, 0, { 0x000203 }},                      /* 0202; 0203; Case map */
+  { 0x000204, 0, { 0x000205 }},                      /* 0204; 0205; Case map */
+  { 0x000206, 0, { 0x000207 }},                      /* 0206; 0207; Case map */
+  { 0x000208, 0, { 0x000209 }},                      /* 0208; 0209; Case map */
+  { 0x00020A, 0, { 0x00020B }},                      /* 020A; 020B; Case map */
+  { 0x00020C, 0, { 0x00020D }},                      /* 020C; 020D; Case map */
+  { 0x00020E, 0, { 0x00020F }},                      /* 020E; 020F; Case map */
+  { 0x000210, 0, { 0x000211 }},                      /* 0210; 0211; Case map */
+  { 0x000212, 0, { 0x000213 }},                      /* 0212; 0213; Case map */
+  { 0x000214, 0, { 0x000215 }},                      /* 0214; 0215; Case map */
+  { 0x000216, 0, { 0x000217 }},                      /* 0216; 0217; Case map */
+  { 0x000218, 0, { 0x000219 }},                      /* 0218; 0219; Case map */
+  { 0x00021A, 0, { 0x00021B }},                      /* 021A; 021B; Case map */
+  { 0x00021C, 0, { 0x00021D }},                      /* 021C; 021D; Case map */
+  { 0x00021E, 0, { 0x00021F }},                      /* 021E; 021F; Case map */
+  { 0x000220, 0, { 0x00019E }},                      /* 0220; 019E; Case map */
+  { 0x000222, 0, { 0x000223 }},                      /* 0222; 0223; Case map */
+  { 0x000224, 0, { 0x000225 }},                      /* 0224; 0225; Case map */
+  { 0x000226, 0, { 0x000227 }},                      /* 0226; 0227; Case map */
+  { 0x000228, 0, { 0x000229 }},                      /* 0228; 0229; Case map */
+  { 0x00022A, 0, { 0x00022B }},                      /* 022A; 022B; Case map */
+  { 0x00022C, 0, { 0x00022D }},                      /* 022C; 022D; Case map */
+  { 0x00022E, 0, { 0x00022F }},                      /* 022E; 022F; Case map */
+  { 0x000230, 0, { 0x000231 }},                      /* 0230; 0231; Case map */
+  { 0x000232, 0, { 0x000233 }},                      /* 0232; 0233; Case map */
+  { 0x000345, 0, { 0x0003B9 }},                      /* 0345; 03B9; Case map */
+  { 0x00037A, 0, { 0x000020,          /* 037A; 0020 03B9; Additional folding */
+                   0x0003B9 }},
+  { 0x000386, 0, { 0x0003AC }},                      /* 0386; 03AC; Case map */
+  { 0x000388, 0, { 0x0003AD }},                      /* 0388; 03AD; Case map */
+  { 0x000389, 0, { 0x0003AE }},                      /* 0389; 03AE; Case map */
+  { 0x00038A, 0, { 0x0003AF }},                      /* 038A; 03AF; Case map */
+  { 0x00038C, 0, { 0x0003CC }},                      /* 038C; 03CC; Case map */
+  { 0x00038E, 0, { 0x0003CD }},                      /* 038E; 03CD; Case map */
+  { 0x00038F, 0, { 0x0003CE }},                      /* 038F; 03CE; Case map */
+  { 0x000390, 0, { 0x0003B9,               /* 0390; 03B9 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x000391, 0, { 0x0003B1 }},                      /* 0391; 03B1; Case map */
+  { 0x000392, 0, { 0x0003B2 }},                      /* 0392; 03B2; Case map */
+  { 0x000393, 0, { 0x0003B3 }},                      /* 0393; 03B3; Case map */
+  { 0x000394, 0, { 0x0003B4 }},                      /* 0394; 03B4; Case map */
+  { 0x000395, 0, { 0x0003B5 }},                      /* 0395; 03B5; Case map */
+  { 0x000396, 0, { 0x0003B6 }},                      /* 0396; 03B6; Case map */
+  { 0x000397, 0, { 0x0003B7 }},                      /* 0397; 03B7; Case map */
+  { 0x000398, 0, { 0x0003B8 }},                      /* 0398; 03B8; Case map */
+  { 0x000399, 0, { 0x0003B9 }},                      /* 0399; 03B9; Case map */
+  { 0x00039A, 0, { 0x0003BA }},                      /* 039A; 03BA; Case map */
+  { 0x00039B, 0, { 0x0003BB }},                      /* 039B; 03BB; Case map */
+  { 0x00039C, 0, { 0x0003BC }},                      /* 039C; 03BC; Case map */
+  { 0x00039D, 0, { 0x0003BD }},                      /* 039D; 03BD; Case map */
+  { 0x00039E, 0, { 0x0003BE }},                      /* 039E; 03BE; Case map */
+  { 0x00039F, 0, { 0x0003BF }},                      /* 039F; 03BF; Case map */
+  { 0x0003A0, 0, { 0x0003C0 }},                      /* 03A0; 03C0; Case map */
+  { 0x0003A1, 0, { 0x0003C1 }},                      /* 03A1; 03C1; Case map */
+  { 0x0003A3, 0, { 0x0003C3 }},                      /* 03A3; 03C3; Case map */
+  { 0x0003A4, 0, { 0x0003C4 }},                      /* 03A4; 03C4; Case map */
+  { 0x0003A5, 0, { 0x0003C5 }},                      /* 03A5; 03C5; Case map */
+  { 0x0003A6, 0, { 0x0003C6 }},                      /* 03A6; 03C6; Case map */
+  { 0x0003A7, 0, { 0x0003C7 }},                      /* 03A7; 03C7; Case map */
+  { 0x0003A8, 0, { 0x0003C8 }},                      /* 03A8; 03C8; Case map */
+  { 0x0003A9, 0, { 0x0003C9 }},                      /* 03A9; 03C9; Case map */
+  { 0x0003AA, 0, { 0x0003CA }},                      /* 03AA; 03CA; Case map */
+  { 0x0003AB, 0, { 0x0003CB }},                      /* 03AB; 03CB; Case map */
+  { 0x0003B0, 0, { 0x0003C5,               /* 03B0; 03C5 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x0003C2, 0, { 0x0003C3 }},                      /* 03C2; 03C3; Case map */
+  { 0x0003D0, 0, { 0x0003B2 }},                      /* 03D0; 03B2; Case map */
+  { 0x0003D1, 0, { 0x0003B8 }},                      /* 03D1; 03B8; Case map */
+  { 0x0003D2, 0, { 0x0003C5 }},            /* 03D2; 03C5; Additional folding */
+  { 0x0003D3, 0, { 0x0003CD }},            /* 03D3; 03CD; Additional folding */
+  { 0x0003D4, 0, { 0x0003CB }},            /* 03D4; 03CB; Additional folding */
+  { 0x0003D5, 0, { 0x0003C6 }},                      /* 03D5; 03C6; Case map */
+  { 0x0003D6, 0, { 0x0003C0 }},                      /* 03D6; 03C0; Case map */
+  { 0x0003D8, 0, { 0x0003D9 }},                      /* 03D8; 03D9; Case map */
+  { 0x0003DA, 0, { 0x0003DB }},                      /* 03DA; 03DB; Case map */
+  { 0x0003DC, 0, { 0x0003DD }},                      /* 03DC; 03DD; Case map */
+  { 0x0003DE, 0, { 0x0003DF }},                      /* 03DE; 03DF; Case map */
+  { 0x0003E0, 0, { 0x0003E1 }},                      /* 03E0; 03E1; Case map */
+  { 0x0003E2, 0, { 0x0003E3 }},                      /* 03E2; 03E3; Case map */
+  { 0x0003E4, 0, { 0x0003E5 }},                      /* 03E4; 03E5; Case map */
+  { 0x0003E6, 0, { 0x0003E7 }},                      /* 03E6; 03E7; Case map */
+  { 0x0003E8, 0, { 0x0003E9 }},                      /* 03E8; 03E9; Case map */
+  { 0x0003EA, 0, { 0x0003EB }},                      /* 03EA; 03EB; Case map */
+  { 0x0003EC, 0, { 0x0003ED }},                      /* 03EC; 03ED; Case map */
+  { 0x0003EE, 0, { 0x0003EF }},                      /* 03EE; 03EF; Case map */
+  { 0x0003F0, 0, { 0x0003BA }},                      /* 03F0; 03BA; Case map */
+  { 0x0003F1, 0, { 0x0003C1 }},                      /* 03F1; 03C1; Case map */
+  { 0x0003F2, 0, { 0x0003C3 }},                      /* 03F2; 03C3; Case map */
+  { 0x0003F4, 0, { 0x0003B8 }},                      /* 03F4; 03B8; Case map */
+  { 0x0003F5, 0, { 0x0003B5 }},                      /* 03F5; 03B5; Case map */
+  { 0x000400, 0, { 0x000450 }},                      /* 0400; 0450; Case map */
+  { 0x000401, 0, { 0x000451 }},                      /* 0401; 0451; Case map */
+  { 0x000402, 0, { 0x000452 }},                      /* 0402; 0452; Case map */
+  { 0x000403, 0, { 0x000453 }},                      /* 0403; 0453; Case map */
+  { 0x000404, 0, { 0x000454 }},                      /* 0404; 0454; Case map */
+  { 0x000405, 0, { 0x000455 }},                      /* 0405; 0455; Case map */
+  { 0x000406, 0, { 0x000456 }},                      /* 0406; 0456; Case map */
+  { 0x000407, 0, { 0x000457 }},                      /* 0407; 0457; Case map */
+  { 0x000408, 0, { 0x000458 }},                      /* 0408; 0458; Case map */
+  { 0x000409, 0, { 0x000459 }},                      /* 0409; 0459; Case map */
+  { 0x00040A, 0, { 0x00045A }},                      /* 040A; 045A; Case map */
+  { 0x00040B, 0, { 0x00045B }},                      /* 040B; 045B; Case map */
+  { 0x00040C, 0, { 0x00045C }},                      /* 040C; 045C; Case map */
+  { 0x00040D, 0, { 0x00045D }},                      /* 040D; 045D; Case map */
+  { 0x00040E, 0, { 0x00045E }},                      /* 040E; 045E; Case map */
+  { 0x00040F, 0, { 0x00045F }},                      /* 040F; 045F; Case map */
+  { 0x000410, 0, { 0x000430 }},                      /* 0410; 0430; Case map */
+  { 0x000411, 0, { 0x000431 }},                      /* 0411; 0431; Case map */
+  { 0x000412, 0, { 0x000432 }},                      /* 0412; 0432; Case map */
+  { 0x000413, 0, { 0x000433 }},                      /* 0413; 0433; Case map */
+  { 0x000414, 0, { 0x000434 }},                      /* 0414; 0434; Case map */
+  { 0x000415, 0, { 0x000435 }},                      /* 0415; 0435; Case map */
+  { 0x000416, 0, { 0x000436 }},                      /* 0416; 0436; Case map */
+  { 0x000417, 0, { 0x000437 }},                      /* 0417; 0437; Case map */
+  { 0x000418, 0, { 0x000438 }},                      /* 0418; 0438; Case map */
+  { 0x000419, 0, { 0x000439 }},                      /* 0419; 0439; Case map */
+  { 0x00041A, 0, { 0x00043A }},                      /* 041A; 043A; Case map */
+  { 0x00041B, 0, { 0x00043B }},                      /* 041B; 043B; Case map */
+  { 0x00041C, 0, { 0x00043C }},                      /* 041C; 043C; Case map */
+  { 0x00041D, 0, { 0x00043D }},                      /* 041D; 043D; Case map */
+  { 0x00041E, 0, { 0x00043E }},                      /* 041E; 043E; Case map */
+  { 0x00041F, 0, { 0x00043F }},                      /* 041F; 043F; Case map */
+  { 0x000420, 0, { 0x000440 }},                      /* 0420; 0440; Case map */
+  { 0x000421, 0, { 0x000441 }},                      /* 0421; 0441; Case map */
+  { 0x000422, 0, { 0x000442 }},                      /* 0422; 0442; Case map */
+  { 0x000423, 0, { 0x000443 }},                      /* 0423; 0443; Case map */
+  { 0x000424, 0, { 0x000444 }},                      /* 0424; 0444; Case map */
+  { 0x000425, 0, { 0x000445 }},                      /* 0425; 0445; Case map */
+  { 0x000426, 0, { 0x000446 }},                      /* 0426; 0446; Case map */
+  { 0x000427, 0, { 0x000447 }},                      /* 0427; 0447; Case map */
+  { 0x000428, 0, { 0x000448 }},                      /* 0428; 0448; Case map */
+  { 0x000429, 0, { 0x000449 }},                      /* 0429; 0449; Case map */
+  { 0x00042A, 0, { 0x00044A }},                      /* 042A; 044A; Case map */
+  { 0x00042B, 0, { 0x00044B }},                      /* 042B; 044B; Case map */
+  { 0x00042C, 0, { 0x00044C }},                      /* 042C; 044C; Case map */
+  { 0x00042D, 0, { 0x00044D }},                      /* 042D; 044D; Case map */
+  { 0x00042E, 0, { 0x00044E }},                      /* 042E; 044E; Case map */
+  { 0x00042F, 0, { 0x00044F }},                      /* 042F; 044F; Case map */
+  { 0x000460, 0, { 0x000461 }},                      /* 0460; 0461; Case map */
+  { 0x000462, 0, { 0x000463 }},                      /* 0462; 0463; Case map */
+  { 0x000464, 0, { 0x000465 }},                      /* 0464; 0465; Case map */
+  { 0x000466, 0, { 0x000467 }},                      /* 0466; 0467; Case map */
+  { 0x000468, 0, { 0x000469 }},                      /* 0468; 0469; Case map */
+  { 0x00046A, 0, { 0x00046B }},                      /* 046A; 046B; Case map */
+  { 0x00046C, 0, { 0x00046D }},                      /* 046C; 046D; Case map */
+  { 0x00046E, 0, { 0x00046F }},                      /* 046E; 046F; Case map */
+  { 0x000470, 0, { 0x000471 }},                      /* 0470; 0471; Case map */
+  { 0x000472, 0, { 0x000473 }},                      /* 0472; 0473; Case map */
+  { 0x000474, 0, { 0x000475 }},                      /* 0474; 0475; Case map */
+  { 0x000476, 0, { 0x000477 }},                      /* 0476; 0477; Case map */
+  { 0x000478, 0, { 0x000479 }},                      /* 0478; 0479; Case map */
+  { 0x00047A, 0, { 0x00047B }},                      /* 047A; 047B; Case map */
+  { 0x00047C, 0, { 0x00047D }},                      /* 047C; 047D; Case map */
+  { 0x00047E, 0, { 0x00047F }},                      /* 047E; 047F; Case map */
+  { 0x000480, 0, { 0x000481 }},                      /* 0480; 0481; Case map */
+  { 0x00048A, 0, { 0x00048B }},                      /* 048A; 048B; Case map */
+  { 0x00048C, 0, { 0x00048D }},                      /* 048C; 048D; Case map */
+  { 0x00048E, 0, { 0x00048F }},                      /* 048E; 048F; Case map */
+  { 0x000490, 0, { 0x000491 }},                      /* 0490; 0491; Case map */
+  { 0x000492, 0, { 0x000493 }},                      /* 0492; 0493; Case map */
+  { 0x000494, 0, { 0x000495 }},                      /* 0494; 0495; Case map */
+  { 0x000496, 0, { 0x000497 }},                      /* 0496; 0497; Case map */
+  { 0x000498, 0, { 0x000499 }},                      /* 0498; 0499; Case map */
+  { 0x00049A, 0, { 0x00049B }},                      /* 049A; 049B; Case map */
+  { 0x00049C, 0, { 0x00049D }},                      /* 049C; 049D; Case map */
+  { 0x00049E, 0, { 0x00049F }},                      /* 049E; 049F; Case map */
+  { 0x0004A0, 0, { 0x0004A1 }},                      /* 04A0; 04A1; Case map */
+  { 0x0004A2, 0, { 0x0004A3 }},                      /* 04A2; 04A3; Case map */
+  { 0x0004A4, 0, { 0x0004A5 }},                      /* 04A4; 04A5; Case map */
+  { 0x0004A6, 0, { 0x0004A7 }},                      /* 04A6; 04A7; Case map */
+  { 0x0004A8, 0, { 0x0004A9 }},                      /* 04A8; 04A9; Case map */
+  { 0x0004AA, 0, { 0x0004AB }},                      /* 04AA; 04AB; Case map */
+  { 0x0004AC, 0, { 0x0004AD }},                      /* 04AC; 04AD; Case map */
+  { 0x0004AE, 0, { 0x0004AF }},                      /* 04AE; 04AF; Case map */
+  { 0x0004B0, 0, { 0x0004B1 }},                      /* 04B0; 04B1; Case map */
+  { 0x0004B2, 0, { 0x0004B3 }},                      /* 04B2; 04B3; Case map */
+  { 0x0004B4, 0, { 0x0004B5 }},                      /* 04B4; 04B5; Case map */
+  { 0x0004B6, 0, { 0x0004B7 }},                      /* 04B6; 04B7; Case map */
+  { 0x0004B8, 0, { 0x0004B9 }},                      /* 04B8; 04B9; Case map */
+  { 0x0004BA, 0, { 0x0004BB }},                      /* 04BA; 04BB; Case map */
+  { 0x0004BC, 0, { 0x0004BD }},                      /* 04BC; 04BD; Case map */
+  { 0x0004BE, 0, { 0x0004BF }},                      /* 04BE; 04BF; Case map */
+  { 0x0004C1, 0, { 0x0004C2 }},                      /* 04C1; 04C2; Case map */
+  { 0x0004C3, 0, { 0x0004C4 }},                      /* 04C3; 04C4; Case map */
+  { 0x0004C5, 0, { 0x0004C6 }},                      /* 04C5; 04C6; Case map */
+  { 0x0004C7, 0, { 0x0004C8 }},                      /* 04C7; 04C8; Case map */
+  { 0x0004C9, 0, { 0x0004CA }},                      /* 04C9; 04CA; Case map */
+  { 0x0004CB, 0, { 0x0004CC }},                      /* 04CB; 04CC; Case map */
+  { 0x0004CD, 0, { 0x0004CE }},                      /* 04CD; 04CE; Case map */
+  { 0x0004D0, 0, { 0x0004D1 }},                      /* 04D0; 04D1; Case map */
+  { 0x0004D2, 0, { 0x0004D3 }},                      /* 04D2; 04D3; Case map */
+  { 0x0004D4, 0, { 0x0004D5 }},                      /* 04D4; 04D5; Case map */
+  { 0x0004D6, 0, { 0x0004D7 }},                      /* 04D6; 04D7; Case map */
+  { 0x0004D8, 0, { 0x0004D9 }},                      /* 04D8; 04D9; Case map */
+  { 0x0004DA, 0, { 0x0004DB }},                      /* 04DA; 04DB; Case map */
+  { 0x0004DC, 0, { 0x0004DD }},                      /* 04DC; 04DD; Case map */
+  { 0x0004DE, 0, { 0x0004DF }},                      /* 04DE; 04DF; Case map */
+  { 0x0004E0, 0, { 0x0004E1 }},                      /* 04E0; 04E1; Case map */
+  { 0x0004E2, 0, { 0x0004E3 }},                      /* 04E2; 04E3; Case map */
+  { 0x0004E4, 0, { 0x0004E5 }},                      /* 04E4; 04E5; Case map */
+  { 0x0004E6, 0, { 0x0004E7 }},                      /* 04E6; 04E7; Case map */
+  { 0x0004E8, 0, { 0x0004E9 }},                      /* 04E8; 04E9; Case map */
+  { 0x0004EA, 0, { 0x0004EB }},                      /* 04EA; 04EB; Case map */
+  { 0x0004EC, 0, { 0x0004ED }},                      /* 04EC; 04ED; Case map */
+  { 0x0004EE, 0, { 0x0004EF }},                      /* 04EE; 04EF; Case map */
+  { 0x0004F0, 0, { 0x0004F1 }},                      /* 04F0; 04F1; Case map */
+  { 0x0004F2, 0, { 0x0004F3 }},                      /* 04F2; 04F3; Case map */
+  { 0x0004F4, 0, { 0x0004F5 }},                      /* 04F4; 04F5; Case map */
+  { 0x0004F8, 0, { 0x0004F9 }},                      /* 04F8; 04F9; Case map */
+  { 0x000500, 0, { 0x000501 }},                      /* 0500; 0501; Case map */
+  { 0x000502, 0, { 0x000503 }},                      /* 0502; 0503; Case map */
+  { 0x000504, 0, { 0x000505 }},                      /* 0504; 0505; Case map */
+  { 0x000506, 0, { 0x000507 }},                      /* 0506; 0507; Case map */
+  { 0x000508, 0, { 0x000509 }},                      /* 0508; 0509; Case map */
+  { 0x00050A, 0, { 0x00050B }},                      /* 050A; 050B; Case map */
+  { 0x00050C, 0, { 0x00050D }},                      /* 050C; 050D; Case map */
+  { 0x00050E, 0, { 0x00050F }},                      /* 050E; 050F; Case map */
+  { 0x000531, 0, { 0x000561 }},                      /* 0531; 0561; Case map */
+  { 0x000532, 0, { 0x000562 }},                      /* 0532; 0562; Case map */
+  { 0x000533, 0, { 0x000563 }},                      /* 0533; 0563; Case map */
+  { 0x000534, 0, { 0x000564 }},                      /* 0534; 0564; Case map */
+  { 0x000535, 0, { 0x000565 }},                      /* 0535; 0565; Case map */
+  { 0x000536, 0, { 0x000566 }},                      /* 0536; 0566; Case map */
+  { 0x000537, 0, { 0x000567 }},                      /* 0537; 0567; Case map */
+  { 0x000538, 0, { 0x000568 }},                      /* 0538; 0568; Case map */
+  { 0x000539, 0, { 0x000569 }},                      /* 0539; 0569; Case map */
+  { 0x00053A, 0, { 0x00056A }},                      /* 053A; 056A; Case map */
+  { 0x00053B, 0, { 0x00056B }},                      /* 053B; 056B; Case map */
+  { 0x00053C, 0, { 0x00056C }},                      /* 053C; 056C; Case map */
+  { 0x00053D, 0, { 0x00056D }},                      /* 053D; 056D; Case map */
+  { 0x00053E, 0, { 0x00056E }},                      /* 053E; 056E; Case map */
+  { 0x00053F, 0, { 0x00056F }},                      /* 053F; 056F; Case map */
+  { 0x000540, 0, { 0x000570 }},                      /* 0540; 0570; Case map */
+  { 0x000541, 0, { 0x000571 }},                      /* 0541; 0571; Case map */
+  { 0x000542, 0, { 0x000572 }},                      /* 0542; 0572; Case map */
+  { 0x000543, 0, { 0x000573 }},                      /* 0543; 0573; Case map */
+  { 0x000544, 0, { 0x000574 }},                      /* 0544; 0574; Case map */
+  { 0x000545, 0, { 0x000575 }},                      /* 0545; 0575; Case map */
+  { 0x000546, 0, { 0x000576 }},                      /* 0546; 0576; Case map */
+  { 0x000547, 0, { 0x000577 }},                      /* 0547; 0577; Case map */
+  { 0x000548, 0, { 0x000578 }},                      /* 0548; 0578; Case map */
+  { 0x000549, 0, { 0x000579 }},                      /* 0549; 0579; Case map */
+  { 0x00054A, 0, { 0x00057A }},                      /* 054A; 057A; Case map */
+  { 0x00054B, 0, { 0x00057B }},                      /* 054B; 057B; Case map */
+  { 0x00054C, 0, { 0x00057C }},                      /* 054C; 057C; Case map */
+  { 0x00054D, 0, { 0x00057D }},                      /* 054D; 057D; Case map */
+  { 0x00054E, 0, { 0x00057E }},                      /* 054E; 057E; Case map */
+  { 0x00054F, 0, { 0x00057F }},                      /* 054F; 057F; Case map */
+  { 0x000550, 0, { 0x000580 }},                      /* 0550; 0580; Case map */
+  { 0x000551, 0, { 0x000581 }},                      /* 0551; 0581; Case map */
+  { 0x000552, 0, { 0x000582 }},                      /* 0552; 0582; Case map */
+  { 0x000553, 0, { 0x000583 }},                      /* 0553; 0583; Case map */
+  { 0x000554, 0, { 0x000584 }},                      /* 0554; 0584; Case map */
+  { 0x000555, 0, { 0x000585 }},                      /* 0555; 0585; Case map */
+  { 0x000556, 0, { 0x000586 }},                      /* 0556; 0586; Case map */
+  { 0x000587, 0, { 0x000565,                    /* 0587; 0565 0582; Case map */
+                   0x000582 }},
+  { 0x001E00, 0, { 0x001E01 }},                      /* 1E00; 1E01; Case map */
+  { 0x001E02, 0, { 0x001E03 }},                      /* 1E02; 1E03; Case map */
+  { 0x001E04, 0, { 0x001E05 }},                      /* 1E04; 1E05; Case map */
+  { 0x001E06, 0, { 0x001E07 }},                      /* 1E06; 1E07; Case map */
+  { 0x001E08, 0, { 0x001E09 }},                      /* 1E08; 1E09; Case map */
+  { 0x001E0A, 0, { 0x001E0B }},                      /* 1E0A; 1E0B; Case map */
+  { 0x001E0C, 0, { 0x001E0D }},                      /* 1E0C; 1E0D; Case map */
+  { 0x001E0E, 0, { 0x001E0F }},                      /* 1E0E; 1E0F; Case map */
+  { 0x001E10, 0, { 0x001E11 }},                      /* 1E10; 1E11; Case map */
+  { 0x001E12, 0, { 0x001E13 }},                      /* 1E12; 1E13; Case map */
+  { 0x001E14, 0, { 0x001E15 }},                      /* 1E14; 1E15; Case map */
+  { 0x001E16, 0, { 0x001E17 }},                      /* 1E16; 1E17; Case map */
+  { 0x001E18, 0, { 0x001E19 }},                      /* 1E18; 1E19; Case map */
+  { 0x001E1A, 0, { 0x001E1B }},                      /* 1E1A; 1E1B; Case map */
+  { 0x001E1C, 0, { 0x001E1D }},                      /* 1E1C; 1E1D; Case map */
+  { 0x001E1E, 0, { 0x001E1F }},                      /* 1E1E; 1E1F; Case map */
+  { 0x001E20, 0, { 0x001E21 }},                      /* 1E20; 1E21; Case map */
+  { 0x001E22, 0, { 0x001E23 }},                      /* 1E22; 1E23; Case map */
+  { 0x001E24, 0, { 0x001E25 }},                      /* 1E24; 1E25; Case map */
+  { 0x001E26, 0, { 0x001E27 }},                      /* 1E26; 1E27; Case map */
+  { 0x001E28, 0, { 0x001E29 }},                      /* 1E28; 1E29; Case map */
+  { 0x001E2A, 0, { 0x001E2B }},                      /* 1E2A; 1E2B; Case map */
+  { 0x001E2C, 0, { 0x001E2D }},                      /* 1E2C; 1E2D; Case map */
+  { 0x001E2E, 0, { 0x001E2F }},                      /* 1E2E; 1E2F; Case map */
+  { 0x001E30, 0, { 0x001E31 }},                      /* 1E30; 1E31; Case map */
+  { 0x001E32, 0, { 0x001E33 }},                      /* 1E32; 1E33; Case map */
+  { 0x001E34, 0, { 0x001E35 }},                      /* 1E34; 1E35; Case map */
+  { 0x001E36, 0, { 0x001E37 }},                      /* 1E36; 1E37; Case map */
+  { 0x001E38, 0, { 0x001E39 }},                      /* 1E38; 1E39; Case map */
+  { 0x001E3A, 0, { 0x001E3B }},                      /* 1E3A; 1E3B; Case map */
+  { 0x001E3C, 0, { 0x001E3D }},                      /* 1E3C; 1E3D; Case map */
+  { 0x001E3E, 0, { 0x001E3F }},                      /* 1E3E; 1E3F; Case map */
+  { 0x001E40, 0, { 0x001E41 }},                      /* 1E40; 1E41; Case map */
+  { 0x001E42, 0, { 0x001E43 }},                      /* 1E42; 1E43; Case map */
+  { 0x001E44, 0, { 0x001E45 }},                      /* 1E44; 1E45; Case map */
+  { 0x001E46, 0, { 0x001E47 }},                      /* 1E46; 1E47; Case map */
+  { 0x001E48, 0, { 0x001E49 }},                      /* 1E48; 1E49; Case map */
+  { 0x001E4A, 0, { 0x001E4B }},                      /* 1E4A; 1E4B; Case map */
+  { 0x001E4C, 0, { 0x001E4D }},                      /* 1E4C; 1E4D; Case map */
+  { 0x001E4E, 0, { 0x001E4F }},                      /* 1E4E; 1E4F; Case map */
+  { 0x001E50, 0, { 0x001E51 }},                      /* 1E50; 1E51; Case map */
+  { 0x001E52, 0, { 0x001E53 }},                      /* 1E52; 1E53; Case map */
+  { 0x001E54, 0, { 0x001E55 }},                      /* 1E54; 1E55; Case map */
+  { 0x001E56, 0, { 0x001E57 }},                      /* 1E56; 1E57; Case map */
+  { 0x001E58, 0, { 0x001E59 }},                      /* 1E58; 1E59; Case map */
+  { 0x001E5A, 0, { 0x001E5B }},                      /* 1E5A; 1E5B; Case map */
+  { 0x001E5C, 0, { 0x001E5D }},                      /* 1E5C; 1E5D; Case map */
+  { 0x001E5E, 0, { 0x001E5F }},                      /* 1E5E; 1E5F; Case map */
+  { 0x001E60, 0, { 0x001E61 }},                      /* 1E60; 1E61; Case map */
+  { 0x001E62, 0, { 0x001E63 }},                      /* 1E62; 1E63; Case map */
+  { 0x001E64, 0, { 0x001E65 }},                      /* 1E64; 1E65; Case map */
+  { 0x001E66, 0, { 0x001E67 }},                      /* 1E66; 1E67; Case map */
+  { 0x001E68, 0, { 0x001E69 }},                      /* 1E68; 1E69; Case map */
+  { 0x001E6A, 0, { 0x001E6B }},                      /* 1E6A; 1E6B; Case map */
+  { 0x001E6C, 0, { 0x001E6D }},                      /* 1E6C; 1E6D; Case map */
+  { 0x001E6E, 0, { 0x001E6F }},                      /* 1E6E; 1E6F; Case map */
+  { 0x001E70, 0, { 0x001E71 }},                      /* 1E70; 1E71; Case map */
+  { 0x001E72, 0, { 0x001E73 }},                      /* 1E72; 1E73; Case map */
+  { 0x001E74, 0, { 0x001E75 }},                      /* 1E74; 1E75; Case map */
+  { 0x001E76, 0, { 0x001E77 }},                      /* 1E76; 1E77; Case map */
+  { 0x001E78, 0, { 0x001E79 }},                      /* 1E78; 1E79; Case map */
+  { 0x001E7A, 0, { 0x001E7B }},                      /* 1E7A; 1E7B; Case map */
+  { 0x001E7C, 0, { 0x001E7D }},                      /* 1E7C; 1E7D; Case map */
+  { 0x001E7E, 0, { 0x001E7F }},                      /* 1E7E; 1E7F; Case map */
+  { 0x001E80, 0, { 0x001E81 }},                      /* 1E80; 1E81; Case map */
+  { 0x001E82, 0, { 0x001E83 }},                      /* 1E82; 1E83; Case map */
+  { 0x001E84, 0, { 0x001E85 }},                      /* 1E84; 1E85; Case map */
+  { 0x001E86, 0, { 0x001E87 }},                      /* 1E86; 1E87; Case map */
+  { 0x001E88, 0, { 0x001E89 }},                      /* 1E88; 1E89; Case map */
+  { 0x001E8A, 0, { 0x001E8B }},                      /* 1E8A; 1E8B; Case map */
+  { 0x001E8C, 0, { 0x001E8D }},                      /* 1E8C; 1E8D; Case map */
+  { 0x001E8E, 0, { 0x001E8F }},                      /* 1E8E; 1E8F; Case map */
+  { 0x001E90, 0, { 0x001E91 }},                      /* 1E90; 1E91; Case map */
+  { 0x001E92, 0, { 0x001E93 }},                      /* 1E92; 1E93; Case map */
+  { 0x001E94, 0, { 0x001E95 }},                      /* 1E94; 1E95; Case map */
+  { 0x001E96, 0, { 0x000068,                    /* 1E96; 0068 0331; Case map */
+                   0x000331 }},
+  { 0x001E97, 0, { 0x000074,                    /* 1E97; 0074 0308; Case map */
+                   0x000308 }},
+  { 0x001E98, 0, { 0x000077,                    /* 1E98; 0077 030A; Case map */
+                   0x00030A }},
+  { 0x001E99, 0, { 0x000079,                    /* 1E99; 0079 030A; Case map */
+                   0x00030A }},
+  { 0x001E9A, 0, { 0x000061,                    /* 1E9A; 0061 02BE; Case map */
+                   0x0002BE }},
+  { 0x001E9B, 0, { 0x001E61 }},                      /* 1E9B; 1E61; Case map */
+  { 0x001EA0, 0, { 0x001EA1 }},                      /* 1EA0; 1EA1; Case map */
+  { 0x001EA2, 0, { 0x001EA3 }},                      /* 1EA2; 1EA3; Case map */
+  { 0x001EA4, 0, { 0x001EA5 }},                      /* 1EA4; 1EA5; Case map */
+  { 0x001EA6, 0, { 0x001EA7 }},                      /* 1EA6; 1EA7; Case map */
+  { 0x001EA8, 0, { 0x001EA9 }},                      /* 1EA8; 1EA9; Case map */
+  { 0x001EAA, 0, { 0x001EAB }},                      /* 1EAA; 1EAB; Case map */
+  { 0x001EAC, 0, { 0x001EAD }},                      /* 1EAC; 1EAD; Case map */
+  { 0x001EAE, 0, { 0x001EAF }},                      /* 1EAE; 1EAF; Case map */
+  { 0x001EB0, 0, { 0x001EB1 }},                      /* 1EB0; 1EB1; Case map */
+  { 0x001EB2, 0, { 0x001EB3 }},                      /* 1EB2; 1EB3; Case map */
+  { 0x001EB4, 0, { 0x001EB5 }},                      /* 1EB4; 1EB5; Case map */
+  { 0x001EB6, 0, { 0x001EB7 }},                      /* 1EB6; 1EB7; Case map */
+  { 0x001EB8, 0, { 0x001EB9 }},                      /* 1EB8; 1EB9; Case map */
+  { 0x001EBA, 0, { 0x001EBB }},                      /* 1EBA; 1EBB; Case map */
+  { 0x001EBC, 0, { 0x001EBD }},                      /* 1EBC; 1EBD; Case map */
+  { 0x001EBE, 0, { 0x001EBF }},                      /* 1EBE; 1EBF; Case map */
+  { 0x001EC0, 0, { 0x001EC1 }},                      /* 1EC0; 1EC1; Case map */
+  { 0x001EC2, 0, { 0x001EC3 }},                      /* 1EC2; 1EC3; Case map */
+  { 0x001EC4, 0, { 0x001EC5 }},                      /* 1EC4; 1EC5; Case map */
+  { 0x001EC6, 0, { 0x001EC7 }},                      /* 1EC6; 1EC7; Case map */
+  { 0x001EC8, 0, { 0x001EC9 }},                      /* 1EC8; 1EC9; Case map */
+  { 0x001ECA, 0, { 0x001ECB }},                      /* 1ECA; 1ECB; Case map */
+  { 0x001ECC, 0, { 0x001ECD }},                      /* 1ECC; 1ECD; Case map */
+  { 0x001ECE, 0, { 0x001ECF }},                      /* 1ECE; 1ECF; Case map */
+  { 0x001ED0, 0, { 0x001ED1 }},                      /* 1ED0; 1ED1; Case map */
+  { 0x001ED2, 0, { 0x001ED3 }},                      /* 1ED2; 1ED3; Case map */
+  { 0x001ED4, 0, { 0x001ED5 }},                      /* 1ED4; 1ED5; Case map */
+  { 0x001ED6, 0, { 0x001ED7 }},                      /* 1ED6; 1ED7; Case map */
+  { 0x001ED8, 0, { 0x001ED9 }},                      /* 1ED8; 1ED9; Case map */
+  { 0x001EDA, 0, { 0x001EDB }},                      /* 1EDA; 1EDB; Case map */
+  { 0x001EDC, 0, { 0x001EDD }},                      /* 1EDC; 1EDD; Case map */
+  { 0x001EDE, 0, { 0x001EDF }},                      /* 1EDE; 1EDF; Case map */
+  { 0x001EE0, 0, { 0x001EE1 }},                      /* 1EE0; 1EE1; Case map */
+  { 0x001EE2, 0, { 0x001EE3 }},                      /* 1EE2; 1EE3; Case map */
+  { 0x001EE4, 0, { 0x001EE5 }},                      /* 1EE4; 1EE5; Case map */
+  { 0x001EE6, 0, { 0x001EE7 }},                      /* 1EE6; 1EE7; Case map */
+  { 0x001EE8, 0, { 0x001EE9 }},                      /* 1EE8; 1EE9; Case map */
+  { 0x001EEA, 0, { 0x001EEB }},                      /* 1EEA; 1EEB; Case map */
+  { 0x001EEC, 0, { 0x001EED }},                      /* 1EEC; 1EED; Case map */
+  { 0x001EEE, 0, { 0x001EEF }},                      /* 1EEE; 1EEF; Case map */
+  { 0x001EF0, 0, { 0x001EF1 }},                      /* 1EF0; 1EF1; Case map */
+  { 0x001EF2, 0, { 0x001EF3 }},                      /* 1EF2; 1EF3; Case map */
+  { 0x001EF4, 0, { 0x001EF5 }},                      /* 1EF4; 1EF5; Case map */
+  { 0x001EF6, 0, { 0x001EF7 }},                      /* 1EF6; 1EF7; Case map */
+  { 0x001EF8, 0, { 0x001EF9 }},                      /* 1EF8; 1EF9; Case map */
+  { 0x001F08, 0, { 0x001F00 }},                      /* 1F08; 1F00; Case map */
+  { 0x001F09, 0, { 0x001F01 }},                      /* 1F09; 1F01; Case map */
+  { 0x001F0A, 0, { 0x001F02 }},                      /* 1F0A; 1F02; Case map */
+  { 0x001F0B, 0, { 0x001F03 }},                      /* 1F0B; 1F03; Case map */
+  { 0x001F0C, 0, { 0x001F04 }},                      /* 1F0C; 1F04; Case map */
+  { 0x001F0D, 0, { 0x001F05 }},                      /* 1F0D; 1F05; Case map */
+  { 0x001F0E, 0, { 0x001F06 }},                      /* 1F0E; 1F06; Case map */
+  { 0x001F0F, 0, { 0x001F07 }},                      /* 1F0F; 1F07; Case map */
+  { 0x001F18, 0, { 0x001F10 }},                      /* 1F18; 1F10; Case map */
+  { 0x001F19, 0, { 0x001F11 }},                      /* 1F19; 1F11; Case map */
+  { 0x001F1A, 0, { 0x001F12 }},                      /* 1F1A; 1F12; Case map */
+  { 0x001F1B, 0, { 0x001F13 }},                      /* 1F1B; 1F13; Case map */
+  { 0x001F1C, 0, { 0x001F14 }},                      /* 1F1C; 1F14; Case map */
+  { 0x001F1D, 0, { 0x001F15 }},                      /* 1F1D; 1F15; Case map */
+  { 0x001F28, 0, { 0x001F20 }},                      /* 1F28; 1F20; Case map */
+  { 0x001F29, 0, { 0x001F21 }},                      /* 1F29; 1F21; Case map */
+  { 0x001F2A, 0, { 0x001F22 }},                      /* 1F2A; 1F22; Case map */
+  { 0x001F2B, 0, { 0x001F23 }},                      /* 1F2B; 1F23; Case map */
+  { 0x001F2C, 0, { 0x001F24 }},                      /* 1F2C; 1F24; Case map */
+  { 0x001F2D, 0, { 0x001F25 }},                      /* 1F2D; 1F25; Case map */
+  { 0x001F2E, 0, { 0x001F26 }},                      /* 1F2E; 1F26; Case map */
+  { 0x001F2F, 0, { 0x001F27 }},                      /* 1F2F; 1F27; Case map */
+  { 0x001F38, 0, { 0x001F30 }},                      /* 1F38; 1F30; Case map */
+  { 0x001F39, 0, { 0x001F31 }},                      /* 1F39; 1F31; Case map */
+  { 0x001F3A, 0, { 0x001F32 }},                      /* 1F3A; 1F32; Case map */
+  { 0x001F3B, 0, { 0x001F33 }},                      /* 1F3B; 1F33; Case map */
+  { 0x001F3C, 0, { 0x001F34 }},                      /* 1F3C; 1F34; Case map */
+  { 0x001F3D, 0, { 0x001F35 }},                      /* 1F3D; 1F35; Case map */
+  { 0x001F3E, 0, { 0x001F36 }},                      /* 1F3E; 1F36; Case map */
+  { 0x001F3F, 0, { 0x001F37 }},                      /* 1F3F; 1F37; Case map */
+  { 0x001F48, 0, { 0x001F40 }},                      /* 1F48; 1F40; Case map */
+  { 0x001F49, 0, { 0x001F41 }},                      /* 1F49; 1F41; Case map */
+  { 0x001F4A, 0, { 0x001F42 }},                      /* 1F4A; 1F42; Case map */
+  { 0x001F4B, 0, { 0x001F43 }},                      /* 1F4B; 1F43; Case map */
+  { 0x001F4C, 0, { 0x001F44 }},                      /* 1F4C; 1F44; Case map */
+  { 0x001F4D, 0, { 0x001F45 }},                      /* 1F4D; 1F45; Case map */
+  { 0x001F50, 0, { 0x0003C5,                    /* 1F50; 03C5 0313; Case map */
+                   0x000313 }},
+  { 0x001F52, 0, { 0x0003C5,               /* 1F52; 03C5 0313 0300; Case map */
+                   0x000313, 0x000300 }},
+  { 0x001F54, 0, { 0x0003C5,               /* 1F54; 03C5 0313 0301; Case map */
+                   0x000313, 0x000301 }},
+  { 0x001F56, 0, { 0x0003C5,               /* 1F56; 03C5 0313 0342; Case map */
+                   0x000313, 0x000342 }},
+  { 0x001F59, 0, { 0x001F51 }},                      /* 1F59; 1F51; Case map */
+  { 0x001F5B, 0, { 0x001F53 }},                      /* 1F5B; 1F53; Case map */
+  { 0x001F5D, 0, { 0x001F55 }},                      /* 1F5D; 1F55; Case map */
+  { 0x001F5F, 0, { 0x001F57 }},                      /* 1F5F; 1F57; Case map */
+  { 0x001F68, 0, { 0x001F60 }},                      /* 1F68; 1F60; Case map */
+  { 0x001F69, 0, { 0x001F61 }},                      /* 1F69; 1F61; Case map */
+  { 0x001F6A, 0, { 0x001F62 }},                      /* 1F6A; 1F62; Case map */
+  { 0x001F6B, 0, { 0x001F63 }},                      /* 1F6B; 1F63; Case map */
+  { 0x001F6C, 0, { 0x001F64 }},                      /* 1F6C; 1F64; Case map */
+  { 0x001F6D, 0, { 0x001F65 }},                      /* 1F6D; 1F65; Case map */
+  { 0x001F6E, 0, { 0x001F66 }},                      /* 1F6E; 1F66; Case map */
+  { 0x001F6F, 0, { 0x001F67 }},                      /* 1F6F; 1F67; Case map */
+  { 0x001F80, 0, { 0x001F00,                    /* 1F80; 1F00 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F81, 0, { 0x001F01,                    /* 1F81; 1F01 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F82, 0, { 0x001F02,                    /* 1F82; 1F02 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F83, 0, { 0x001F03,                    /* 1F83; 1F03 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F84, 0, { 0x001F04,                    /* 1F84; 1F04 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F85, 0, { 0x001F05,                    /* 1F85; 1F05 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F86, 0, { 0x001F06,                    /* 1F86; 1F06 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F87, 0, { 0x001F07,                    /* 1F87; 1F07 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F88, 0, { 0x001F00,                    /* 1F88; 1F00 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F89, 0, { 0x001F01,                    /* 1F89; 1F01 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8A, 0, { 0x001F02,                    /* 1F8A; 1F02 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8B, 0, { 0x001F03,                    /* 1F8B; 1F03 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8C, 0, { 0x001F04,                    /* 1F8C; 1F04 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8D, 0, { 0x001F05,                    /* 1F8D; 1F05 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8E, 0, { 0x001F06,                    /* 1F8E; 1F06 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8F, 0, { 0x001F07,                    /* 1F8F; 1F07 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F90, 0, { 0x001F20,                    /* 1F90; 1F20 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F91, 0, { 0x001F21,                    /* 1F91; 1F21 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F92, 0, { 0x001F22,                    /* 1F92; 1F22 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F93, 0, { 0x001F23,                    /* 1F93; 1F23 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F94, 0, { 0x001F24,                    /* 1F94; 1F24 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F95, 0, { 0x001F25,                    /* 1F95; 1F25 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F96, 0, { 0x001F26,                    /* 1F96; 1F26 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F97, 0, { 0x001F27,                    /* 1F97; 1F27 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F98, 0, { 0x001F20,                    /* 1F98; 1F20 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F99, 0, { 0x001F21,                    /* 1F99; 1F21 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9A, 0, { 0x001F22,                    /* 1F9A; 1F22 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9B, 0, { 0x001F23,                    /* 1F9B; 1F23 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9C, 0, { 0x001F24,                    /* 1F9C; 1F24 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9D, 0, { 0x001F25,                    /* 1F9D; 1F25 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9E, 0, { 0x001F26,                    /* 1F9E; 1F26 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9F, 0, { 0x001F27,                    /* 1F9F; 1F27 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA0, 0, { 0x001F60,                    /* 1FA0; 1F60 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA1, 0, { 0x001F61,                    /* 1FA1; 1F61 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA2, 0, { 0x001F62,                    /* 1FA2; 1F62 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA3, 0, { 0x001F63,                    /* 1FA3; 1F63 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA4, 0, { 0x001F64,                    /* 1FA4; 1F64 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA5, 0, { 0x001F65,                    /* 1FA5; 1F65 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA6, 0, { 0x001F66,                    /* 1FA6; 1F66 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA7, 0, { 0x001F67,                    /* 1FA7; 1F67 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA8, 0, { 0x001F60,                    /* 1FA8; 1F60 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA9, 0, { 0x001F61,                    /* 1FA9; 1F61 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAA, 0, { 0x001F62,                    /* 1FAA; 1F62 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAB, 0, { 0x001F63,                    /* 1FAB; 1F63 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAC, 0, { 0x001F64,                    /* 1FAC; 1F64 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAD, 0, { 0x001F65,                    /* 1FAD; 1F65 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAE, 0, { 0x001F66,                    /* 1FAE; 1F66 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAF, 0, { 0x001F67,                    /* 1FAF; 1F67 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB2, 0, { 0x001F70,                    /* 1FB2; 1F70 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB3, 0, { 0x0003B1,                    /* 1FB3; 03B1 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB4, 0, { 0x0003AC,                    /* 1FB4; 03AC 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB6, 0, { 0x0003B1,                    /* 1FB6; 03B1 0342; Case map */
+                   0x000342 }},
+  { 0x001FB7, 0, { 0x0003B1,               /* 1FB7; 03B1 0342 03B9; Case map */
+                   0x000342, 0x0003B9 }},
+  { 0x001FB8, 0, { 0x001FB0 }},                      /* 1FB8; 1FB0; Case map */
+  { 0x001FB9, 0, { 0x001FB1 }},                      /* 1FB9; 1FB1; Case map */
+  { 0x001FBA, 0, { 0x001F70 }},                      /* 1FBA; 1F70; Case map */
+  { 0x001FBB, 0, { 0x001F71 }},                      /* 1FBB; 1F71; Case map */
+  { 0x001FBC, 0, { 0x0003B1,                    /* 1FBC; 03B1 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FBE, 0, { 0x0003B9 }},                      /* 1FBE; 03B9; Case map */
+  { 0x001FC2, 0, { 0x001F74,                    /* 1FC2; 1F74 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FC3, 0, { 0x0003B7,                    /* 1FC3; 03B7 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FC4, 0, { 0x0003AE,                    /* 1FC4; 03AE 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FC6, 0, { 0x0003B7,                    /* 1FC6; 03B7 0342; Case map */
+                   0x000342 }},
+  { 0x001FC7, 0, { 0x0003B7,               /* 1FC7; 03B7 0342 03B9; Case map */
+                   0x000342, 0x0003B9 }},
+  { 0x001FC8, 0, { 0x001F72 }},                      /* 1FC8; 1F72; Case map */
+  { 0x001FC9, 0, { 0x001F73 }},                      /* 1FC9; 1F73; Case map */
+  { 0x001FCA, 0, { 0x001F74 }},                      /* 1FCA; 1F74; Case map */
+  { 0x001FCB, 0, { 0x001F75 }},                      /* 1FCB; 1F75; Case map */
+  { 0x001FCC, 0, { 0x0003B7,                    /* 1FCC; 03B7 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FD2, 0, { 0x0003B9,               /* 1FD2; 03B9 0308 0300; Case map */
+                   0x000308, 0x000300 }},
+  { 0x001FD3, 0, { 0x0003B9,               /* 1FD3; 03B9 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x001FD6, 0, { 0x0003B9,                    /* 1FD6; 03B9 0342; Case map */
+                   0x000342 }},
+  { 0x001FD7, 0, { 0x0003B9,               /* 1FD7; 03B9 0308 0342; Case map */
+                   0x000308, 0x000342 }},
+  { 0x001FD8, 0, { 0x001FD0 }},                      /* 1FD8; 1FD0; Case map */
+  { 0x001FD9, 0, { 0x001FD1 }},                      /* 1FD9; 1FD1; Case map */
+  { 0x001FDA, 0, { 0x001F76 }},                      /* 1FDA; 1F76; Case map */
+  { 0x001FDB, 0, { 0x001F77 }},                      /* 1FDB; 1F77; Case map */
+  { 0x001FE2, 0, { 0x0003C5,               /* 1FE2; 03C5 0308 0300; Case map */
+                   0x000308, 0x000300 }},
+  { 0x001FE3, 0, { 0x0003C5,               /* 1FE3; 03C5 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x001FE4, 0, { 0x0003C1,                    /* 1FE4; 03C1 0313; Case map */
+                   0x000313 }},
+  { 0x001FE6, 0, { 0x0003C5,                    /* 1FE6; 03C5 0342; Case map */
+                   0x000342 }},
+  { 0x001FE7, 0, { 0x0003C5,               /* 1FE7; 03C5 0308 0342; Case map */
+                   0x000308, 0x000342 }},
+  { 0x001FE8, 0, { 0x001FE0 }},                      /* 1FE8; 1FE0; Case map */
+  { 0x001FE9, 0, { 0x001FE1 }},                      /* 1FE9; 1FE1; Case map */
+  { 0x001FEA, 0, { 0x001F7A }},                      /* 1FEA; 1F7A; Case map */
+  { 0x001FEB, 0, { 0x001F7B }},                      /* 1FEB; 1F7B; Case map */
+  { 0x001FEC, 0, { 0x001FE5 }},                      /* 1FEC; 1FE5; Case map */
+  { 0x001FF2, 0, { 0x001F7C,                    /* 1FF2; 1F7C 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FF3, 0, { 0x0003C9,                    /* 1FF3; 03C9 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FF4, 0, { 0x0003CE,                    /* 1FF4; 03CE 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FF6, 0, { 0x0003C9,                    /* 1FF6; 03C9 0342; Case map */
+                   0x000342 }},
+  { 0x001FF7, 0, { 0x0003C9,               /* 1FF7; 03C9 0342 03B9; Case map */
+                   0x000342, 0x0003B9 }},
+  { 0x001FF8, 0, { 0x001F78 }},                      /* 1FF8; 1F78; Case map */
+  { 0x001FF9, 0, { 0x001F79 }},                      /* 1FF9; 1F79; Case map */
+  { 0x001FFA, 0, { 0x001F7C }},                      /* 1FFA; 1F7C; Case map */
+  { 0x001FFB, 0, { 0x001F7D }},                      /* 1FFB; 1F7D; Case map */
+  { 0x001FFC, 0, { 0x0003C9,                    /* 1FFC; 03C9 03B9; Case map */
+                   0x0003B9 }},
+  { 0x0020A8, 0, { 0x000072,          /* 20A8; 0072 0073; Additional folding */
+                   0x000073 }},
+  { 0x002102, 0, { 0x000063 }},            /* 2102; 0063; Additional folding */
+  { 0x002103, 0, { 0x0000B0,          /* 2103; 00B0 0063; Additional folding */
+                   0x000063 }},
+  { 0x002107, 0, { 0x00025B }},            /* 2107; 025B; Additional folding */
+  { 0x002109, 0, { 0x0000B0,          /* 2109; 00B0 0066; Additional folding */
+                   0x000066 }},
+  { 0x00210B, 0, { 0x000068 }},            /* 210B; 0068; Additional folding */
+  { 0x00210C, 0, { 0x000068 }},            /* 210C; 0068; Additional folding */
+  { 0x00210D, 0, { 0x000068 }},            /* 210D; 0068; Additional folding */
+  { 0x002110, 0, { 0x000069 }},            /* 2110; 0069; Additional folding */
+  { 0x002111, 0, { 0x000069 }},            /* 2111; 0069; Additional folding */
+  { 0x002112, 0, { 0x00006C }},            /* 2112; 006C; Additional folding */
+  { 0x002115, 0, { 0x00006E }},            /* 2115; 006E; Additional folding */
+  { 0x002116, 0, { 0x00006E,          /* 2116; 006E 006F; Additional folding */
+                   0x00006F }},
+  { 0x002119, 0, { 0x000070 }},            /* 2119; 0070; Additional folding */
+  { 0x00211A, 0, { 0x000071 }},            /* 211A; 0071; Additional folding */
+  { 0x00211B, 0, { 0x000072 }},            /* 211B; 0072; Additional folding */
+  { 0x00211C, 0, { 0x000072 }},            /* 211C; 0072; Additional folding */
+  { 0x00211D, 0, { 0x000072 }},            /* 211D; 0072; Additional folding */
+  { 0x002120, 0, { 0x000073,          /* 2120; 0073 006D; Additional folding */
+                   0x00006D }},
+  { 0x002121, 0, { 0x000074,     /* 2121; 0074 0065 006C; Additional folding */
+                   0x000065, 0x00006C }},
+  { 0x002122, 0, { 0x000074,          /* 2122; 0074 006D; Additional folding */
+                   0x00006D }},
+  { 0x002124, 0, { 0x00007A }},            /* 2124; 007A; Additional folding */
+  { 0x002126, 0, { 0x0003C9 }},                      /* 2126; 03C9; Case map */
+  { 0x002128, 0, { 0x00007A }},            /* 2128; 007A; Additional folding */
+  { 0x00212A, 0, { 0x00006B }},                      /* 212A; 006B; Case map */
+  { 0x00212B, 0, { 0x0000E5 }},                      /* 212B; 00E5; Case map */
+  { 0x00212C, 0, { 0x000062 }},            /* 212C; 0062; Additional folding */
+  { 0x00212D, 0, { 0x000063 }},            /* 212D; 0063; Additional folding */
+  { 0x002130, 0, { 0x000065 }},            /* 2130; 0065; Additional folding */
+  { 0x002131, 0, { 0x000066 }},            /* 2131; 0066; Additional folding */
+  { 0x002133, 0, { 0x00006D }},            /* 2133; 006D; Additional folding */
+  { 0x00213E, 0, { 0x0003B3 }},            /* 213E; 03B3; Additional folding */
+  { 0x00213F, 0, { 0x0003C0 }},            /* 213F; 03C0; Additional folding */
+  { 0x002145, 0, { 0x000064 }},            /* 2145; 0064; Additional folding */
+  { 0x002160, 0, { 0x002170 }},                      /* 2160; 2170; Case map */
+  { 0x002161, 0, { 0x002171 }},                      /* 2161; 2171; Case map */
+  { 0x002162, 0, { 0x002172 }},                      /* 2162; 2172; Case map */
+  { 0x002163, 0, { 0x002173 }},                      /* 2163; 2173; Case map */
+  { 0x002164, 0, { 0x002174 }},                      /* 2164; 2174; Case map */
+  { 0x002165, 0, { 0x002175 }},                      /* 2165; 2175; Case map */
+  { 0x002166, 0, { 0x002176 }},                      /* 2166; 2176; Case map */
+  { 0x002167, 0, { 0x002177 }},                      /* 2167; 2177; Case map */
+  { 0x002168, 0, { 0x002178 }},                      /* 2168; 2178; Case map */
+  { 0x002169, 0, { 0x002179 }},                      /* 2169; 2179; Case map */
+  { 0x00216A, 0, { 0x00217A }},                      /* 216A; 217A; Case map */
+  { 0x00216B, 0, { 0x00217B }},                      /* 216B; 217B; Case map */
+  { 0x00216C, 0, { 0x00217C }},                      /* 216C; 217C; Case map */
+  { 0x00216D, 0, { 0x00217D }},                      /* 216D; 217D; Case map */
+  { 0x00216E, 0, { 0x00217E }},                      /* 216E; 217E; Case map */
+  { 0x00216F, 0, { 0x00217F }},                      /* 216F; 217F; Case map */
+  { 0x0024B6, 0, { 0x0024D0 }},                      /* 24B6; 24D0; Case map */
+  { 0x0024B7, 0, { 0x0024D1 }},                      /* 24B7; 24D1; Case map */
+  { 0x0024B8, 0, { 0x0024D2 }},                      /* 24B8; 24D2; Case map */
+  { 0x0024B9, 0, { 0x0024D3 }},                      /* 24B9; 24D3; Case map */
+  { 0x0024BA, 0, { 0x0024D4 }},                      /* 24BA; 24D4; Case map */
+  { 0x0024BB, 0, { 0x0024D5 }},                      /* 24BB; 24D5; Case map */
+  { 0x0024BC, 0, { 0x0024D6 }},                      /* 24BC; 24D6; Case map */
+  { 0x0024BD, 0, { 0x0024D7 }},                      /* 24BD; 24D7; Case map */
+  { 0x0024BE, 0, { 0x0024D8 }},                      /* 24BE; 24D8; Case map */
+  { 0x0024BF, 0, { 0x0024D9 }},                      /* 24BF; 24D9; Case map */
+  { 0x0024C0, 0, { 0x0024DA }},                      /* 24C0; 24DA; Case map */
+  { 0x0024C1, 0, { 0x0024DB }},                      /* 24C1; 24DB; Case map */
+  { 0x0024C2, 0, { 0x0024DC }},                      /* 24C2; 24DC; Case map */
+  { 0x0024C3, 0, { 0x0024DD }},                      /* 24C3; 24DD; Case map */
+  { 0x0024C4, 0, { 0x0024DE }},                      /* 24C4; 24DE; Case map */
+  { 0x0024C5, 0, { 0x0024DF }},                      /* 24C5; 24DF; Case map */
+  { 0x0024C6, 0, { 0x0024E0 }},                      /* 24C6; 24E0; Case map */
+  { 0x0024C7, 0, { 0x0024E1 }},                      /* 24C7; 24E1; Case map */
+  { 0x0024C8, 0, { 0x0024E2 }},                      /* 24C8; 24E2; Case map */
+  { 0x0024C9, 0, { 0x0024E3 }},                      /* 24C9; 24E3; Case map */
+  { 0x0024CA, 0, { 0x0024E4 }},                      /* 24CA; 24E4; Case map */
+  { 0x0024CB, 0, { 0x0024E5 }},                      /* 24CB; 24E5; Case map */
+  { 0x0024CC, 0, { 0x0024E6 }},                      /* 24CC; 24E6; Case map */
+  { 0x0024CD, 0, { 0x0024E7 }},                      /* 24CD; 24E7; Case map */
+  { 0x0024CE, 0, { 0x0024E8 }},                      /* 24CE; 24E8; Case map */
+  { 0x0024CF, 0, { 0x0024E9 }},                      /* 24CF; 24E9; Case map */
+  { 0x003371, 0, { 0x000068,     /* 3371; 0068 0070 0061; Additional folding */
+                   0x000070, 0x000061 }},
+  { 0x003373, 0, { 0x000061,          /* 3373; 0061 0075; Additional folding */
+                   0x000075 }},
+  { 0x003375, 0, { 0x00006F,          /* 3375; 006F 0076; Additional folding */
+                   0x000076 }},
+  { 0x003380, 0, { 0x000070,          /* 3380; 0070 0061; Additional folding */
+                   0x000061 }},
+  { 0x003381, 0, { 0x00006E,          /* 3381; 006E 0061; Additional folding */
+                   0x000061 }},
+  { 0x003382, 0, { 0x0003BC,          /* 3382; 03BC 0061; Additional folding */
+                   0x000061 }},
+  { 0x003383, 0, { 0x00006D,          /* 3383; 006D 0061; Additional folding */
+                   0x000061 }},
+  { 0x003384, 0, { 0x00006B,          /* 3384; 006B 0061; Additional folding */
+                   0x000061 }},
+  { 0x003385, 0, { 0x00006B,          /* 3385; 006B 0062; Additional folding */
+                   0x000062 }},
+  { 0x003386, 0, { 0x00006D,          /* 3386; 006D 0062; Additional folding */
+                   0x000062 }},
+  { 0x003387, 0, { 0x000067,          /* 3387; 0067 0062; Additional folding */
+                   0x000062 }},
+  { 0x00338A, 0, { 0x000070,          /* 338A; 0070 0066; Additional folding */
+                   0x000066 }},
+  { 0x00338B, 0, { 0x00006E,          /* 338B; 006E 0066; Additional folding */
+                   0x000066 }},
+  { 0x00338C, 0, { 0x0003BC,          /* 338C; 03BC 0066; Additional folding */
+                   0x000066 }},
+  { 0x003390, 0, { 0x000068,          /* 3390; 0068 007A; Additional folding */
+                   0x00007A }},
+  { 0x003391, 0, { 0x00006B,     /* 3391; 006B 0068 007A; Additional folding */
+                   0x000068, 0x00007A }},
+  { 0x003392, 0, { 0x00006D,     /* 3392; 006D 0068 007A; Additional folding */
+                   0x000068, 0x00007A }},
+  { 0x003393, 0, { 0x000067,     /* 3393; 0067 0068 007A; Additional folding */
+                   0x000068, 0x00007A }},
+  { 0x003394, 0, { 0x000074,     /* 3394; 0074 0068 007A; Additional folding */
+                   0x000068, 0x00007A }},
+  { 0x0033A9, 0, { 0x000070,          /* 33A9; 0070 0061; Additional folding */
+                   0x000061 }},
+  { 0x0033AA, 0, { 0x00006B,     /* 33AA; 006B 0070 0061; Additional folding */
+                   0x000070, 0x000061 }},
+  { 0x0033AB, 0, { 0x00006D,     /* 33AB; 006D 0070 0061; Additional folding */
+                   0x000070, 0x000061 }},
+  { 0x0033AC, 0, { 0x000067,     /* 33AC; 0067 0070 0061; Additional folding */
+                   0x000070, 0x000061 }},
+  { 0x0033B4, 0, { 0x000070,          /* 33B4; 0070 0076; Additional folding */
+                   0x000076 }},
+  { 0x0033B5, 0, { 0x00006E,          /* 33B5; 006E 0076; Additional folding */
+                   0x000076 }},
+  { 0x0033B6, 0, { 0x0003BC,          /* 33B6; 03BC 0076; Additional folding */
+                   0x000076 }},
+  { 0x0033B7, 0, { 0x00006D,          /* 33B7; 006D 0076; Additional folding */
+                   0x000076 }},
+  { 0x0033B8, 0, { 0x00006B,          /* 33B8; 006B 0076; Additional folding */
+                   0x000076 }},
+  { 0x0033B9, 0, { 0x00006D,          /* 33B9; 006D 0076; Additional folding */
+                   0x000076 }},
+  { 0x0033BA, 0, { 0x000070,          /* 33BA; 0070 0077; Additional folding */
+                   0x000077 }},
+  { 0x0033BB, 0, { 0x00006E,          /* 33BB; 006E 0077; Additional folding */
+                   0x000077 }},
+  { 0x0033BC, 0, { 0x0003BC,          /* 33BC; 03BC 0077; Additional folding */
+                   0x000077 }},
+  { 0x0033BD, 0, { 0x00006D,          /* 33BD; 006D 0077; Additional folding */
+                   0x000077 }},
+  { 0x0033BE, 0, { 0x00006B,          /* 33BE; 006B 0077; Additional folding */
+                   0x000077 }},
+  { 0x0033BF, 0, { 0x00006D,          /* 33BF; 006D 0077; Additional folding */
+                   0x000077 }},
+  { 0x0033C0, 0, { 0x00006B,          /* 33C0; 006B 03C9; Additional folding */
+                   0x0003C9 }},
+  { 0x0033C1, 0, { 0x00006D,          /* 33C1; 006D 03C9; Additional folding */
+                   0x0003C9 }},
+  { 0x0033C3, 0, { 0x000062,          /* 33C3; 0062 0071; Additional folding */
+                   0x000071 }},
+  { 0x0033C6, 0, { 0x000063, /* 33C6; 0063 2215 006B 0067; Additional folding */
+                   0x002215, 0x00006B, 0x000067 }},
+  { 0x0033C7, 0, { 0x000063,     /* 33C7; 0063 006F 002E; Additional folding */
+                   0x00006F, 0x00002E }},
+  { 0x0033C8, 0, { 0x000064,          /* 33C8; 0064 0062; Additional folding */
+                   0x000062 }},
+  { 0x0033C9, 0, { 0x000067,          /* 33C9; 0067 0079; Additional folding */
+                   0x000079 }},
+  { 0x0033CB, 0, { 0x000068,          /* 33CB; 0068 0070; Additional folding */
+                   0x000070 }},
+  { 0x0033CD, 0, { 0x00006B,          /* 33CD; 006B 006B; Additional folding */
+                   0x00006B }},
+  { 0x0033CE, 0, { 0x00006B,          /* 33CE; 006B 006D; Additional folding */
+                   0x00006D }},
+  { 0x0033D7, 0, { 0x000070,          /* 33D7; 0070 0068; Additional folding */
+                   0x000068 }},
+  { 0x0033D9, 0, { 0x000070,     /* 33D9; 0070 0070 006D; Additional folding */
+                   0x000070, 0x00006D }},
+  { 0x0033DA, 0, { 0x000070,          /* 33DA; 0070 0072; Additional folding */
+                   0x000072 }},
+  { 0x0033DC, 0, { 0x000073,          /* 33DC; 0073 0076; Additional folding */
+                   0x000076 }},
+  { 0x0033DD, 0, { 0x000077,          /* 33DD; 0077 0062; Additional folding */
+                   0x000062 }},
+  { 0x00FB00, 0, { 0x000066,                    /* FB00; 0066 0066; Case map */
+                   0x000066 }},
+  { 0x00FB01, 0, { 0x000066,                    /* FB01; 0066 0069; Case map */
+                   0x000069 }},
+  { 0x00FB02, 0, { 0x000066,                    /* FB02; 0066 006C; Case map */
+                   0x00006C }},
+  { 0x00FB03, 0, { 0x000066,               /* FB03; 0066 0066 0069; Case map */
+                   0x000066, 0x000069 }},
+  { 0x00FB04, 0, { 0x000066,               /* FB04; 0066 0066 006C; Case map */
+                   0x000066, 0x00006C }},
+  { 0x00FB05, 0, { 0x000073,                    /* FB05; 0073 0074; Case map */
+                   0x000074 }},
+  { 0x00FB06, 0, { 0x000073,                    /* FB06; 0073 0074; Case map */
+                   0x000074 }},
+  { 0x00FB13, 0, { 0x000574,                    /* FB13; 0574 0576; Case map */
+                   0x000576 }},
+  { 0x00FB14, 0, { 0x000574,                    /* FB14; 0574 0565; Case map */
+                   0x000565 }},
+  { 0x00FB15, 0, { 0x000574,                    /* FB15; 0574 056B; Case map */
+                   0x00056B }},
+  { 0x00FB16, 0, { 0x00057E,                    /* FB16; 057E 0576; Case map */
+                   0x000576 }},
+  { 0x00FB17, 0, { 0x000574,                    /* FB17; 0574 056D; Case map */
+                   0x00056D }},
+  { 0x00FF21, 0, { 0x00FF41 }},                      /* FF21; FF41; Case map */
+  { 0x00FF22, 0, { 0x00FF42 }},                      /* FF22; FF42; Case map */
+  { 0x00FF23, 0, { 0x00FF43 }},                      /* FF23; FF43; Case map */
+  { 0x00FF24, 0, { 0x00FF44 }},                      /* FF24; FF44; Case map */
+  { 0x00FF25, 0, { 0x00FF45 }},                      /* FF25; FF45; Case map */
+  { 0x00FF26, 0, { 0x00FF46 }},                      /* FF26; FF46; Case map */
+  { 0x00FF27, 0, { 0x00FF47 }},                      /* FF27; FF47; Case map */
+  { 0x00FF28, 0, { 0x00FF48 }},                      /* FF28; FF48; Case map */
+  { 0x00FF29, 0, { 0x00FF49 }},                      /* FF29; FF49; Case map */
+  { 0x00FF2A, 0, { 0x00FF4A }},                      /* FF2A; FF4A; Case map */
+  { 0x00FF2B, 0, { 0x00FF4B }},                      /* FF2B; FF4B; Case map */
+  { 0x00FF2C, 0, { 0x00FF4C }},                      /* FF2C; FF4C; Case map */
+  { 0x00FF2D, 0, { 0x00FF4D }},                      /* FF2D; FF4D; Case map */
+  { 0x00FF2E, 0, { 0x00FF4E }},                      /* FF2E; FF4E; Case map */
+  { 0x00FF2F, 0, { 0x00FF4F }},                      /* FF2F; FF4F; Case map */
+  { 0x00FF30, 0, { 0x00FF50 }},                      /* FF30; FF50; Case map */
+  { 0x00FF31, 0, { 0x00FF51 }},                      /* FF31; FF51; Case map */
+  { 0x00FF32, 0, { 0x00FF52 }},                      /* FF32; FF52; Case map */
+  { 0x00FF33, 0, { 0x00FF53 }},                      /* FF33; FF53; Case map */
+  { 0x00FF34, 0, { 0x00FF54 }},                      /* FF34; FF54; Case map */
+  { 0x00FF35, 0, { 0x00FF55 }},                      /* FF35; FF55; Case map */
+  { 0x00FF36, 0, { 0x00FF56 }},                      /* FF36; FF56; Case map */
+  { 0x00FF37, 0, { 0x00FF57 }},                      /* FF37; FF57; Case map */
+  { 0x00FF38, 0, { 0x00FF58 }},                      /* FF38; FF58; Case map */
+  { 0x00FF39, 0, { 0x00FF59 }},                      /* FF39; FF59; Case map */
+  { 0x00FF3A, 0, { 0x00FF5A }},                      /* FF3A; FF5A; Case map */
+  { 0x010400, 0, { 0x010428 }},                    /* 10400; 10428; Case map */
+  { 0x010401, 0, { 0x010429 }},                    /* 10401; 10429; Case map */
+  { 0x010402, 0, { 0x01042A }},                    /* 10402; 1042A; Case map */
+  { 0x010403, 0, { 0x01042B }},                    /* 10403; 1042B; Case map */
+  { 0x010404, 0, { 0x01042C }},                    /* 10404; 1042C; Case map */
+  { 0x010405, 0, { 0x01042D }},                    /* 10405; 1042D; Case map */
+  { 0x010406, 0, { 0x01042E }},                    /* 10406; 1042E; Case map */
+  { 0x010407, 0, { 0x01042F }},                    /* 10407; 1042F; Case map */
+  { 0x010408, 0, { 0x010430 }},                    /* 10408; 10430; Case map */
+  { 0x010409, 0, { 0x010431 }},                    /* 10409; 10431; Case map */
+  { 0x01040A, 0, { 0x010432 }},                    /* 1040A; 10432; Case map */
+  { 0x01040B, 0, { 0x010433 }},                    /* 1040B; 10433; Case map */
+  { 0x01040C, 0, { 0x010434 }},                    /* 1040C; 10434; Case map */
+  { 0x01040D, 0, { 0x010435 }},                    /* 1040D; 10435; Case map */
+  { 0x01040E, 0, { 0x010436 }},                    /* 1040E; 10436; Case map */
+  { 0x01040F, 0, { 0x010437 }},                    /* 1040F; 10437; Case map */
+  { 0x010410, 0, { 0x010438 }},                    /* 10410; 10438; Case map */
+  { 0x010411, 0, { 0x010439 }},                    /* 10411; 10439; Case map */
+  { 0x010412, 0, { 0x01043A }},                    /* 10412; 1043A; Case map */
+  { 0x010413, 0, { 0x01043B }},                    /* 10413; 1043B; Case map */
+  { 0x010414, 0, { 0x01043C }},                    /* 10414; 1043C; Case map */
+  { 0x010415, 0, { 0x01043D }},                    /* 10415; 1043D; Case map */
+  { 0x010416, 0, { 0x01043E }},                    /* 10416; 1043E; Case map */
+  { 0x010417, 0, { 0x01043F }},                    /* 10417; 1043F; Case map */
+  { 0x010418, 0, { 0x010440 }},                    /* 10418; 10440; Case map */
+  { 0x010419, 0, { 0x010441 }},                    /* 10419; 10441; Case map */
+  { 0x01041A, 0, { 0x010442 }},                    /* 1041A; 10442; Case map */
+  { 0x01041B, 0, { 0x010443 }},                    /* 1041B; 10443; Case map */
+  { 0x01041C, 0, { 0x010444 }},                    /* 1041C; 10444; Case map */
+  { 0x01041D, 0, { 0x010445 }},                    /* 1041D; 10445; Case map */
+  { 0x01041E, 0, { 0x010446 }},                    /* 1041E; 10446; Case map */
+  { 0x01041F, 0, { 0x010447 }},                    /* 1041F; 10447; Case map */
+  { 0x010420, 0, { 0x010448 }},                    /* 10420; 10448; Case map */
+  { 0x010421, 0, { 0x010449 }},                    /* 10421; 10449; Case map */
+  { 0x010422, 0, { 0x01044A }},                    /* 10422; 1044A; Case map */
+  { 0x010423, 0, { 0x01044B }},                    /* 10423; 1044B; Case map */
+  { 0x010424, 0, { 0x01044C }},                    /* 10424; 1044C; Case map */
+  { 0x010425, 0, { 0x01044D }},                    /* 10425; 1044D; Case map */
+  { 0x01D400, 0, { 0x000061 }},           /* 1D400; 0061; Additional folding */
+  { 0x01D401, 0, { 0x000062 }},           /* 1D401; 0062; Additional folding */
+  { 0x01D402, 0, { 0x000063 }},           /* 1D402; 0063; Additional folding */
+  { 0x01D403, 0, { 0x000064 }},           /* 1D403; 0064; Additional folding */
+  { 0x01D404, 0, { 0x000065 }},           /* 1D404; 0065; Additional folding */
+  { 0x01D405, 0, { 0x000066 }},           /* 1D405; 0066; Additional folding */
+  { 0x01D406, 0, { 0x000067 }},           /* 1D406; 0067; Additional folding */
+  { 0x01D407, 0, { 0x000068 }},           /* 1D407; 0068; Additional folding */
+  { 0x01D408, 0, { 0x000069 }},           /* 1D408; 0069; Additional folding */
+  { 0x01D409, 0, { 0x00006A }},           /* 1D409; 006A; Additional folding */
+  { 0x01D40A, 0, { 0x00006B }},           /* 1D40A; 006B; Additional folding */
+  { 0x01D40B, 0, { 0x00006C }},           /* 1D40B; 006C; Additional folding */
+  { 0x01D40C, 0, { 0x00006D }},           /* 1D40C; 006D; Additional folding */
+  { 0x01D40D, 0, { 0x00006E }},           /* 1D40D; 006E; Additional folding */
+  { 0x01D40E, 0, { 0x00006F }},           /* 1D40E; 006F; Additional folding */
+  { 0x01D40F, 0, { 0x000070 }},           /* 1D40F; 0070; Additional folding */
+  { 0x01D410, 0, { 0x000071 }},           /* 1D410; 0071; Additional folding */
+  { 0x01D411, 0, { 0x000072 }},           /* 1D411; 0072; Additional folding */
+  { 0x01D412, 0, { 0x000073 }},           /* 1D412; 0073; Additional folding */
+  { 0x01D413, 0, { 0x000074 }},           /* 1D413; 0074; Additional folding */
+  { 0x01D414, 0, { 0x000075 }},           /* 1D414; 0075; Additional folding */
+  { 0x01D415, 0, { 0x000076 }},           /* 1D415; 0076; Additional folding */
+  { 0x01D416, 0, { 0x000077 }},           /* 1D416; 0077; Additional folding */
+  { 0x01D417, 0, { 0x000078 }},           /* 1D417; 0078; Additional folding */
+  { 0x01D418, 0, { 0x000079 }},           /* 1D418; 0079; Additional folding */
+  { 0x01D419, 0, { 0x00007A }},           /* 1D419; 007A; Additional folding */
+  { 0x01D434, 0, { 0x000061 }},           /* 1D434; 0061; Additional folding */
+  { 0x01D435, 0, { 0x000062 }},           /* 1D435; 0062; Additional folding */
+  { 0x01D436, 0, { 0x000063 }},           /* 1D436; 0063; Additional folding */
+  { 0x01D437, 0, { 0x000064 }},           /* 1D437; 0064; Additional folding */
+  { 0x01D438, 0, { 0x000065 }},           /* 1D438; 0065; Additional folding */
+  { 0x01D439, 0, { 0x000066 }},           /* 1D439; 0066; Additional folding */
+  { 0x01D43A, 0, { 0x000067 }},           /* 1D43A; 0067; Additional folding */
+  { 0x01D43B, 0, { 0x000068 }},           /* 1D43B; 0068; Additional folding */
+  { 0x01D43C, 0, { 0x000069 }},           /* 1D43C; 0069; Additional folding */
+  { 0x01D43D, 0, { 0x00006A }},           /* 1D43D; 006A; Additional folding */
+  { 0x01D43E, 0, { 0x00006B }},           /* 1D43E; 006B; Additional folding */
+  { 0x01D43F, 0, { 0x00006C }},           /* 1D43F; 006C; Additional folding */
+  { 0x01D440, 0, { 0x00006D }},           /* 1D440; 006D; Additional folding */
+  { 0x01D441, 0, { 0x00006E }},           /* 1D441; 006E; Additional folding */
+  { 0x01D442, 0, { 0x00006F }},           /* 1D442; 006F; Additional folding */
+  { 0x01D443, 0, { 0x000070 }},           /* 1D443; 0070; Additional folding */
+  { 0x01D444, 0, { 0x000071 }},           /* 1D444; 0071; Additional folding */
+  { 0x01D445, 0, { 0x000072 }},           /* 1D445; 0072; Additional folding */
+  { 0x01D446, 0, { 0x000073 }},           /* 1D446; 0073; Additional folding */
+  { 0x01D447, 0, { 0x000074 }},           /* 1D447; 0074; Additional folding */
+  { 0x01D448, 0, { 0x000075 }},           /* 1D448; 0075; Additional folding */
+  { 0x01D449, 0, { 0x000076 }},           /* 1D449; 0076; Additional folding */
+  { 0x01D44A, 0, { 0x000077 }},           /* 1D44A; 0077; Additional folding */
+  { 0x01D44B, 0, { 0x000078 }},           /* 1D44B; 0078; Additional folding */
+  { 0x01D44C, 0, { 0x000079 }},           /* 1D44C; 0079; Additional folding */
+  { 0x01D44D, 0, { 0x00007A }},           /* 1D44D; 007A; Additional folding */
+  { 0x01D468, 0, { 0x000061 }},           /* 1D468; 0061; Additional folding */
+  { 0x01D469, 0, { 0x000062 }},           /* 1D469; 0062; Additional folding */
+  { 0x01D46A, 0, { 0x000063 }},           /* 1D46A; 0063; Additional folding */
+  { 0x01D46B, 0, { 0x000064 }},           /* 1D46B; 0064; Additional folding */
+  { 0x01D46C, 0, { 0x000065 }},           /* 1D46C; 0065; Additional folding */
+  { 0x01D46D, 0, { 0x000066 }},           /* 1D46D; 0066; Additional folding */
+  { 0x01D46E, 0, { 0x000067 }},           /* 1D46E; 0067; Additional folding */
+  { 0x01D46F, 0, { 0x000068 }},           /* 1D46F; 0068; Additional folding */
+  { 0x01D470, 0, { 0x000069 }},           /* 1D470; 0069; Additional folding */
+  { 0x01D471, 0, { 0x00006A }},           /* 1D471; 006A; Additional folding */
+  { 0x01D472, 0, { 0x00006B }},           /* 1D472; 006B; Additional folding */
+  { 0x01D473, 0, { 0x00006C }},           /* 1D473; 006C; Additional folding */
+  { 0x01D474, 0, { 0x00006D }},           /* 1D474; 006D; Additional folding */
+  { 0x01D475, 0, { 0x00006E }},           /* 1D475; 006E; Additional folding */
+  { 0x01D476, 0, { 0x00006F }},           /* 1D476; 006F; Additional folding */
+  { 0x01D477, 0, { 0x000070 }},           /* 1D477; 0070; Additional folding */
+  { 0x01D478, 0, { 0x000071 }},           /* 1D478; 0071; Additional folding */
+  { 0x01D479, 0, { 0x000072 }},           /* 1D479; 0072; Additional folding */
+  { 0x01D47A, 0, { 0x000073 }},           /* 1D47A; 0073; Additional folding */
+  { 0x01D47B, 0, { 0x000074 }},           /* 1D47B; 0074; Additional folding */
+  { 0x01D47C, 0, { 0x000075 }},           /* 1D47C; 0075; Additional folding */
+  { 0x01D47D, 0, { 0x000076 }},           /* 1D47D; 0076; Additional folding */
+  { 0x01D47E, 0, { 0x000077 }},           /* 1D47E; 0077; Additional folding */
+  { 0x01D47F, 0, { 0x000078 }},           /* 1D47F; 0078; Additional folding */
+  { 0x01D480, 0, { 0x000079 }},           /* 1D480; 0079; Additional folding */
+  { 0x01D481, 0, { 0x00007A }},           /* 1D481; 007A; Additional folding */
+  { 0x01D49C, 0, { 0x000061 }},           /* 1D49C; 0061; Additional folding */
+  { 0x01D49E, 0, { 0x000063 }},           /* 1D49E; 0063; Additional folding */
+  { 0x01D49F, 0, { 0x000064 }},           /* 1D49F; 0064; Additional folding */
+  { 0x01D4A2, 0, { 0x000067 }},           /* 1D4A2; 0067; Additional folding */
+  { 0x01D4A5, 0, { 0x00006A }},           /* 1D4A5; 006A; Additional folding */
+  { 0x01D4A6, 0, { 0x00006B }},           /* 1D4A6; 006B; Additional folding */
+  { 0x01D4A9, 0, { 0x00006E }},           /* 1D4A9; 006E; Additional folding */
+  { 0x01D4AA, 0, { 0x00006F }},           /* 1D4AA; 006F; Additional folding */
+  { 0x01D4AB, 0, { 0x000070 }},           /* 1D4AB; 0070; Additional folding */
+  { 0x01D4AC, 0, { 0x000071 }},           /* 1D4AC; 0071; Additional folding */
+  { 0x01D4AE, 0, { 0x000073 }},           /* 1D4AE; 0073; Additional folding */
+  { 0x01D4AF, 0, { 0x000074 }},           /* 1D4AF; 0074; Additional folding */
+  { 0x01D4B0, 0, { 0x000075 }},           /* 1D4B0; 0075; Additional folding */
+  { 0x01D4B1, 0, { 0x000076 }},           /* 1D4B1; 0076; Additional folding */
+  { 0x01D4B2, 0, { 0x000077 }},           /* 1D4B2; 0077; Additional folding */
+  { 0x01D4B3, 0, { 0x000078 }},           /* 1D4B3; 0078; Additional folding */
+  { 0x01D4B4, 0, { 0x000079 }},           /* 1D4B4; 0079; Additional folding */
+  { 0x01D4B5, 0, { 0x00007A }},           /* 1D4B5; 007A; Additional folding */
+  { 0x01D4D0, 0, { 0x000061 }},           /* 1D4D0; 0061; Additional folding */
+  { 0x01D4D1, 0, { 0x000062 }},           /* 1D4D1; 0062; Additional folding */
+  { 0x01D4D2, 0, { 0x000063 }},           /* 1D4D2; 0063; Additional folding */
+  { 0x01D4D3, 0, { 0x000064 }},           /* 1D4D3; 0064; Additional folding */
+  { 0x01D4D4, 0, { 0x000065 }},           /* 1D4D4; 0065; Additional folding */
+  { 0x01D4D5, 0, { 0x000066 }},           /* 1D4D5; 0066; Additional folding */
+  { 0x01D4D6, 0, { 0x000067 }},           /* 1D4D6; 0067; Additional folding */
+  { 0x01D4D7, 0, { 0x000068 }},           /* 1D4D7; 0068; Additional folding */
+  { 0x01D4D8, 0, { 0x000069 }},           /* 1D4D8; 0069; Additional folding */
+  { 0x01D4D9, 0, { 0x00006A }},           /* 1D4D9; 006A; Additional folding */
+  { 0x01D4DA, 0, { 0x00006B }},           /* 1D4DA; 006B; Additional folding */
+  { 0x01D4DB, 0, { 0x00006C }},           /* 1D4DB; 006C; Additional folding */
+  { 0x01D4DC, 0, { 0x00006D }},           /* 1D4DC; 006D; Additional folding */
+  { 0x01D4DD, 0, { 0x00006E }},           /* 1D4DD; 006E; Additional folding */
+  { 0x01D4DE, 0, { 0x00006F }},           /* 1D4DE; 006F; Additional folding */
+  { 0x01D4DF, 0, { 0x000070 }},           /* 1D4DF; 0070; Additional folding */
+  { 0x01D4E0, 0, { 0x000071 }},           /* 1D4E0; 0071; Additional folding */
+  { 0x01D4E1, 0, { 0x000072 }},           /* 1D4E1; 0072; Additional folding */
+  { 0x01D4E2, 0, { 0x000073 }},           /* 1D4E2; 0073; Additional folding */
+  { 0x01D4E3, 0, { 0x000074 }},           /* 1D4E3; 0074; Additional folding */
+  { 0x01D4E4, 0, { 0x000075 }},           /* 1D4E4; 0075; Additional folding */
+  { 0x01D4E5, 0, { 0x000076 }},           /* 1D4E5; 0076; Additional folding */
+  { 0x01D4E6, 0, { 0x000077 }},           /* 1D4E6; 0077; Additional folding */
+  { 0x01D4E7, 0, { 0x000078 }},           /* 1D4E7; 0078; Additional folding */
+  { 0x01D4E8, 0, { 0x000079 }},           /* 1D4E8; 0079; Additional folding */
+  { 0x01D4E9, 0, { 0x00007A }},           /* 1D4E9; 007A; Additional folding */
+  { 0x01D504, 0, { 0x000061 }},           /* 1D504; 0061; Additional folding */
+  { 0x01D505, 0, { 0x000062 }},           /* 1D505; 0062; Additional folding */
+  { 0x01D507, 0, { 0x000064 }},           /* 1D507; 0064; Additional folding */
+  { 0x01D508, 0, { 0x000065 }},           /* 1D508; 0065; Additional folding */
+  { 0x01D509, 0, { 0x000066 }},           /* 1D509; 0066; Additional folding */
+  { 0x01D50A, 0, { 0x000067 }},           /* 1D50A; 0067; Additional folding */
+  { 0x01D50D, 0, { 0x00006A }},           /* 1D50D; 006A; Additional folding */
+  { 0x01D50E, 0, { 0x00006B }},           /* 1D50E; 006B; Additional folding */
+  { 0x01D50F, 0, { 0x00006C }},           /* 1D50F; 006C; Additional folding */
+  { 0x01D510, 0, { 0x00006D }},           /* 1D510; 006D; Additional folding */
+  { 0x01D511, 0, { 0x00006E }},           /* 1D511; 006E; Additional folding */
+  { 0x01D512, 0, { 0x00006F }},           /* 1D512; 006F; Additional folding */
+  { 0x01D513, 0, { 0x000070 }},           /* 1D513; 0070; Additional folding */
+  { 0x01D514, 0, { 0x000071 }},           /* 1D514; 0071; Additional folding */
+  { 0x01D516, 0, { 0x000073 }},           /* 1D516; 0073; Additional folding */
+  { 0x01D517, 0, { 0x000074 }},           /* 1D517; 0074; Additional folding */
+  { 0x01D518, 0, { 0x000075 }},           /* 1D518; 0075; Additional folding */
+  { 0x01D519, 0, { 0x000076 }},           /* 1D519; 0076; Additional folding */
+  { 0x01D51A, 0, { 0x000077 }},           /* 1D51A; 0077; Additional folding */
+  { 0x01D51B, 0, { 0x000078 }},           /* 1D51B; 0078; Additional folding */
+  { 0x01D51C, 0, { 0x000079 }},           /* 1D51C; 0079; Additional folding */
+  { 0x01D538, 0, { 0x000061 }},           /* 1D538; 0061; Additional folding */
+  { 0x01D539, 0, { 0x000062 }},           /* 1D539; 0062; Additional folding */
+  { 0x01D53B, 0, { 0x000064 }},           /* 1D53B; 0064; Additional folding */
+  { 0x01D53C, 0, { 0x000065 }},           /* 1D53C; 0065; Additional folding */
+  { 0x01D53D, 0, { 0x000066 }},           /* 1D53D; 0066; Additional folding */
+  { 0x01D53E, 0, { 0x000067 }},           /* 1D53E; 0067; Additional folding */
+  { 0x01D540, 0, { 0x000069 }},           /* 1D540; 0069; Additional folding */
+  { 0x01D541, 0, { 0x00006A }},           /* 1D541; 006A; Additional folding */
+  { 0x01D542, 0, { 0x00006B }},           /* 1D542; 006B; Additional folding */
+  { 0x01D543, 0, { 0x00006C }},           /* 1D543; 006C; Additional folding */
+  { 0x01D544, 0, { 0x00006D }},           /* 1D544; 006D; Additional folding */
+  { 0x01D546, 0, { 0x00006F }},           /* 1D546; 006F; Additional folding */
+  { 0x01D54A, 0, { 0x000073 }},           /* 1D54A; 0073; Additional folding */
+  { 0x01D54B, 0, { 0x000074 }},           /* 1D54B; 0074; Additional folding */
+  { 0x01D54C, 0, { 0x000075 }},           /* 1D54C; 0075; Additional folding */
+  { 0x01D54D, 0, { 0x000076 }},           /* 1D54D; 0076; Additional folding */
+  { 0x01D54E, 0, { 0x000077 }},           /* 1D54E; 0077; Additional folding */
+  { 0x01D54F, 0, { 0x000078 }},           /* 1D54F; 0078; Additional folding */
+  { 0x01D550, 0, { 0x000079 }},           /* 1D550; 0079; Additional folding */
+  { 0x01D56C, 0, { 0x000061 }},           /* 1D56C; 0061; Additional folding */
+  { 0x01D56D, 0, { 0x000062 }},           /* 1D56D; 0062; Additional folding */
+  { 0x01D56E, 0, { 0x000063 }},           /* 1D56E; 0063; Additional folding */
+  { 0x01D56F, 0, { 0x000064 }},           /* 1D56F; 0064; Additional folding */
+  { 0x01D570, 0, { 0x000065 }},           /* 1D570; 0065; Additional folding */
+  { 0x01D571, 0, { 0x000066 }},           /* 1D571; 0066; Additional folding */
+  { 0x01D572, 0, { 0x000067 }},           /* 1D572; 0067; Additional folding */
+  { 0x01D573, 0, { 0x000068 }},           /* 1D573; 0068; Additional folding */
+  { 0x01D574, 0, { 0x000069 }},           /* 1D574; 0069; Additional folding */
+  { 0x01D575, 0, { 0x00006A }},           /* 1D575; 006A; Additional folding */
+  { 0x01D576, 0, { 0x00006B }},           /* 1D576; 006B; Additional folding */
+  { 0x01D577, 0, { 0x00006C }},           /* 1D577; 006C; Additional folding */
+  { 0x01D578, 0, { 0x00006D }},           /* 1D578; 006D; Additional folding */
+  { 0x01D579, 0, { 0x00006E }},           /* 1D579; 006E; Additional folding */
+  { 0x01D57A, 0, { 0x00006F }},           /* 1D57A; 006F; Additional folding */
+  { 0x01D57B, 0, { 0x000070 }},           /* 1D57B; 0070; Additional folding */
+  { 0x01D57C, 0, { 0x000071 }},           /* 1D57C; 0071; Additional folding */
+  { 0x01D57D, 0, { 0x000072 }},           /* 1D57D; 0072; Additional folding */
+  { 0x01D57E, 0, { 0x000073 }},           /* 1D57E; 0073; Additional folding */
+  { 0x01D57F, 0, { 0x000074 }},           /* 1D57F; 0074; Additional folding */
+  { 0x01D580, 0, { 0x000075 }},           /* 1D580; 0075; Additional folding */
+  { 0x01D581, 0, { 0x000076 }},           /* 1D581; 0076; Additional folding */
+  { 0x01D582, 0, { 0x000077 }},           /* 1D582; 0077; Additional folding */
+  { 0x01D583, 0, { 0x000078 }},           /* 1D583; 0078; Additional folding */
+  { 0x01D584, 0, { 0x000079 }},           /* 1D584; 0079; Additional folding */
+  { 0x01D585, 0, { 0x00007A }},           /* 1D585; 007A; Additional folding */
+  { 0x01D5A0, 0, { 0x000061 }},           /* 1D5A0; 0061; Additional folding */
+  { 0x01D5A1, 0, { 0x000062 }},           /* 1D5A1; 0062; Additional folding */
+  { 0x01D5A2, 0, { 0x000063 }},           /* 1D5A2; 0063; Additional folding */
+  { 0x01D5A3, 0, { 0x000064 }},           /* 1D5A3; 0064; Additional folding */
+  { 0x01D5A4, 0, { 0x000065 }},           /* 1D5A4; 0065; Additional folding */
+  { 0x01D5A5, 0, { 0x000066 }},           /* 1D5A5; 0066; Additional folding */
+  { 0x01D5A6, 0, { 0x000067 }},           /* 1D5A6; 0067; Additional folding */
+  { 0x01D5A7, 0, { 0x000068 }},           /* 1D5A7; 0068; Additional folding */
+  { 0x01D5A8, 0, { 0x000069 }},           /* 1D5A8; 0069; Additional folding */
+  { 0x01D5A9, 0, { 0x00006A }},           /* 1D5A9; 006A; Additional folding */
+  { 0x01D5AA, 0, { 0x00006B }},           /* 1D5AA; 006B; Additional folding */
+  { 0x01D5AB, 0, { 0x00006C }},           /* 1D5AB; 006C; Additional folding */
+  { 0x01D5AC, 0, { 0x00006D }},           /* 1D5AC; 006D; Additional folding */
+  { 0x01D5AD, 0, { 0x00006E }},           /* 1D5AD; 006E; Additional folding */
+  { 0x01D5AE, 0, { 0x00006F }},           /* 1D5AE; 006F; Additional folding */
+  { 0x01D5AF, 0, { 0x000070 }},           /* 1D5AF; 0070; Additional folding */
+  { 0x01D5B0, 0, { 0x000071 }},           /* 1D5B0; 0071; Additional folding */
+  { 0x01D5B1, 0, { 0x000072 }},           /* 1D5B1; 0072; Additional folding */
+  { 0x01D5B2, 0, { 0x000073 }},           /* 1D5B2; 0073; Additional folding */
+  { 0x01D5B3, 0, { 0x000074 }},           /* 1D5B3; 0074; Additional folding */
+  { 0x01D5B4, 0, { 0x000075 }},           /* 1D5B4; 0075; Additional folding */
+  { 0x01D5B5, 0, { 0x000076 }},           /* 1D5B5; 0076; Additional folding */
+  { 0x01D5B6, 0, { 0x000077 }},           /* 1D5B6; 0077; Additional folding */
+  { 0x01D5B7, 0, { 0x000078 }},           /* 1D5B7; 0078; Additional folding */
+  { 0x01D5B8, 0, { 0x000079 }},           /* 1D5B8; 0079; Additional folding */
+  { 0x01D5B9, 0, { 0x00007A }},           /* 1D5B9; 007A; Additional folding */
+  { 0x01D5D4, 0, { 0x000061 }},           /* 1D5D4; 0061; Additional folding */
+  { 0x01D5D5, 0, { 0x000062 }},           /* 1D5D5; 0062; Additional folding */
+  { 0x01D5D6, 0, { 0x000063 }},           /* 1D5D6; 0063; Additional folding */
+  { 0x01D5D7, 0, { 0x000064 }},           /* 1D5D7; 0064; Additional folding */
+  { 0x01D5D8, 0, { 0x000065 }},           /* 1D5D8; 0065; Additional folding */
+  { 0x01D5D9, 0, { 0x000066 }},           /* 1D5D9; 0066; Additional folding */
+  { 0x01D5DA, 0, { 0x000067 }},           /* 1D5DA; 0067; Additional folding */
+  { 0x01D5DB, 0, { 0x000068 }},           /* 1D5DB; 0068; Additional folding */
+  { 0x01D5DC, 0, { 0x000069 }},           /* 1D5DC; 0069; Additional folding */
+  { 0x01D5DD, 0, { 0x00006A }},           /* 1D5DD; 006A; Additional folding */
+  { 0x01D5DE, 0, { 0x00006B }},           /* 1D5DE; 006B; Additional folding */
+  { 0x01D5DF, 0, { 0x00006C }},           /* 1D5DF; 006C; Additional folding */
+  { 0x01D5E0, 0, { 0x00006D }},           /* 1D5E0; 006D; Additional folding */
+  { 0x01D5E1, 0, { 0x00006E }},           /* 1D5E1; 006E; Additional folding */
+  { 0x01D5E2, 0, { 0x00006F }},           /* 1D5E2; 006F; Additional folding */
+  { 0x01D5E3, 0, { 0x000070 }},           /* 1D5E3; 0070; Additional folding */
+  { 0x01D5E4, 0, { 0x000071 }},           /* 1D5E4; 0071; Additional folding */
+  { 0x01D5E5, 0, { 0x000072 }},           /* 1D5E5; 0072; Additional folding */
+  { 0x01D5E6, 0, { 0x000073 }},           /* 1D5E6; 0073; Additional folding */
+  { 0x01D5E7, 0, { 0x000074 }},           /* 1D5E7; 0074; Additional folding */
+  { 0x01D5E8, 0, { 0x000075 }},           /* 1D5E8; 0075; Additional folding */
+  { 0x01D5E9, 0, { 0x000076 }},           /* 1D5E9; 0076; Additional folding */
+  { 0x01D5EA, 0, { 0x000077 }},           /* 1D5EA; 0077; Additional folding */
+  { 0x01D5EB, 0, { 0x000078 }},           /* 1D5EB; 0078; Additional folding */
+  { 0x01D5EC, 0, { 0x000079 }},           /* 1D5EC; 0079; Additional folding */
+  { 0x01D5ED, 0, { 0x00007A }},           /* 1D5ED; 007A; Additional folding */
+  { 0x01D608, 0, { 0x000061 }},           /* 1D608; 0061; Additional folding */
+  { 0x01D609, 0, { 0x000062 }},           /* 1D609; 0062; Additional folding */
+  { 0x01D60A, 0, { 0x000063 }},           /* 1D60A; 0063; Additional folding */
+  { 0x01D60B, 0, { 0x000064 }},           /* 1D60B; 0064; Additional folding */
+  { 0x01D60C, 0, { 0x000065 }},           /* 1D60C; 0065; Additional folding */
+  { 0x01D60D, 0, { 0x000066 }},           /* 1D60D; 0066; Additional folding */
+  { 0x01D60E, 0, { 0x000067 }},           /* 1D60E; 0067; Additional folding */
+  { 0x01D60F, 0, { 0x000068 }},           /* 1D60F; 0068; Additional folding */
+  { 0x01D610, 0, { 0x000069 }},           /* 1D610; 0069; Additional folding */
+  { 0x01D611, 0, { 0x00006A }},           /* 1D611; 006A; Additional folding */
+  { 0x01D612, 0, { 0x00006B }},           /* 1D612; 006B; Additional folding */
+  { 0x01D613, 0, { 0x00006C }},           /* 1D613; 006C; Additional folding */
+  { 0x01D614, 0, { 0x00006D }},           /* 1D614; 006D; Additional folding */
+  { 0x01D615, 0, { 0x00006E }},           /* 1D615; 006E; Additional folding */
+  { 0x01D616, 0, { 0x00006F }},           /* 1D616; 006F; Additional folding */
+  { 0x01D617, 0, { 0x000070 }},           /* 1D617; 0070; Additional folding */
+  { 0x01D618, 0, { 0x000071 }},           /* 1D618; 0071; Additional folding */
+  { 0x01D619, 0, { 0x000072 }},           /* 1D619; 0072; Additional folding */
+  { 0x01D61A, 0, { 0x000073 }},           /* 1D61A; 0073; Additional folding */
+  { 0x01D61B, 0, { 0x000074 }},           /* 1D61B; 0074; Additional folding */
+  { 0x01D61C, 0, { 0x000075 }},           /* 1D61C; 0075; Additional folding */
+  { 0x01D61D, 0, { 0x000076 }},           /* 1D61D; 0076; Additional folding */
+  { 0x01D61E, 0, { 0x000077 }},           /* 1D61E; 0077; Additional folding */
+  { 0x01D61F, 0, { 0x000078 }},           /* 1D61F; 0078; Additional folding */
+  { 0x01D620, 0, { 0x000079 }},           /* 1D620; 0079; Additional folding */
+  { 0x01D621, 0, { 0x00007A }},           /* 1D621; 007A; Additional folding */
+  { 0x01D63C, 0, { 0x000061 }},           /* 1D63C; 0061; Additional folding */
+  { 0x01D63D, 0, { 0x000062 }},           /* 1D63D; 0062; Additional folding */
+  { 0x01D63E, 0, { 0x000063 }},           /* 1D63E; 0063; Additional folding */
+  { 0x01D63F, 0, { 0x000064 }},           /* 1D63F; 0064; Additional folding */
+  { 0x01D640, 0, { 0x000065 }},           /* 1D640; 0065; Additional folding */
+  { 0x01D641, 0, { 0x000066 }},           /* 1D641; 0066; Additional folding */
+  { 0x01D642, 0, { 0x000067 }},           /* 1D642; 0067; Additional folding */
+  { 0x01D643, 0, { 0x000068 }},           /* 1D643; 0068; Additional folding */
+  { 0x01D644, 0, { 0x000069 }},           /* 1D644; 0069; Additional folding */
+  { 0x01D645, 0, { 0x00006A }},           /* 1D645; 006A; Additional folding */
+  { 0x01D646, 0, { 0x00006B }},           /* 1D646; 006B; Additional folding */
+  { 0x01D647, 0, { 0x00006C }},           /* 1D647; 006C; Additional folding */
+  { 0x01D648, 0, { 0x00006D }},           /* 1D648; 006D; Additional folding */
+  { 0x01D649, 0, { 0x00006E }},           /* 1D649; 006E; Additional folding */
+  { 0x01D64A, 0, { 0x00006F }},           /* 1D64A; 006F; Additional folding */
+  { 0x01D64B, 0, { 0x000070 }},           /* 1D64B; 0070; Additional folding */
+  { 0x01D64C, 0, { 0x000071 }},           /* 1D64C; 0071; Additional folding */
+  { 0x01D64D, 0, { 0x000072 }},           /* 1D64D; 0072; Additional folding */
+  { 0x01D64E, 0, { 0x000073 }},           /* 1D64E; 0073; Additional folding */
+  { 0x01D64F, 0, { 0x000074 }},           /* 1D64F; 0074; Additional folding */
+  { 0x01D650, 0, { 0x000075 }},           /* 1D650; 0075; Additional folding */
+  { 0x01D651, 0, { 0x000076 }},           /* 1D651; 0076; Additional folding */
+  { 0x01D652, 0, { 0x000077 }},           /* 1D652; 0077; Additional folding */
+  { 0x01D653, 0, { 0x000078 }},           /* 1D653; 0078; Additional folding */
+  { 0x01D654, 0, { 0x000079 }},           /* 1D654; 0079; Additional folding */
+  { 0x01D655, 0, { 0x00007A }},           /* 1D655; 007A; Additional folding */
+  { 0x01D670, 0, { 0x000061 }},           /* 1D670; 0061; Additional folding */
+  { 0x01D671, 0, { 0x000062 }},           /* 1D671; 0062; Additional folding */
+  { 0x01D672, 0, { 0x000063 }},           /* 1D672; 0063; Additional folding */
+  { 0x01D673, 0, { 0x000064 }},           /* 1D673; 0064; Additional folding */
+  { 0x01D674, 0, { 0x000065 }},           /* 1D674; 0065; Additional folding */
+  { 0x01D675, 0, { 0x000066 }},           /* 1D675; 0066; Additional folding */
+  { 0x01D676, 0, { 0x000067 }},           /* 1D676; 0067; Additional folding */
+  { 0x01D677, 0, { 0x000068 }},           /* 1D677; 0068; Additional folding */
+  { 0x01D678, 0, { 0x000069 }},           /* 1D678; 0069; Additional folding */
+  { 0x01D679, 0, { 0x00006A }},           /* 1D679; 006A; Additional folding */
+  { 0x01D67A, 0, { 0x00006B }},           /* 1D67A; 006B; Additional folding */
+  { 0x01D67B, 0, { 0x00006C }},           /* 1D67B; 006C; Additional folding */
+  { 0x01D67C, 0, { 0x00006D }},           /* 1D67C; 006D; Additional folding */
+  { 0x01D67D, 0, { 0x00006E }},           /* 1D67D; 006E; Additional folding */
+  { 0x01D67E, 0, { 0x00006F }},           /* 1D67E; 006F; Additional folding */
+  { 0x01D67F, 0, { 0x000070 }},           /* 1D67F; 0070; Additional folding */
+  { 0x01D680, 0, { 0x000071 }},           /* 1D680; 0071; Additional folding */
+  { 0x01D681, 0, { 0x000072 }},           /* 1D681; 0072; Additional folding */
+  { 0x01D682, 0, { 0x000073 }},           /* 1D682; 0073; Additional folding */
+  { 0x01D683, 0, { 0x000074 }},           /* 1D683; 0074; Additional folding */
+  { 0x01D684, 0, { 0x000075 }},           /* 1D684; 0075; Additional folding */
+  { 0x01D685, 0, { 0x000076 }},           /* 1D685; 0076; Additional folding */
+  { 0x01D686, 0, { 0x000077 }},           /* 1D686; 0077; Additional folding */
+  { 0x01D687, 0, { 0x000078 }},           /* 1D687; 0078; Additional folding */
+  { 0x01D688, 0, { 0x000079 }},           /* 1D688; 0079; Additional folding */
+  { 0x01D689, 0, { 0x00007A }},           /* 1D689; 007A; Additional folding */
+  { 0x01D6A8, 0, { 0x0003B1 }},           /* 1D6A8; 03B1; Additional folding */
+  { 0x01D6A9, 0, { 0x0003B2 }},           /* 1D6A9; 03B2; Additional folding */
+  { 0x01D6AA, 0, { 0x0003B3 }},           /* 1D6AA; 03B3; Additional folding */
+  { 0x01D6AB, 0, { 0x0003B4 }},           /* 1D6AB; 03B4; Additional folding */
+  { 0x01D6AC, 0, { 0x0003B5 }},           /* 1D6AC; 03B5; Additional folding */
+  { 0x01D6AD, 0, { 0x0003B6 }},           /* 1D6AD; 03B6; Additional folding */
+  { 0x01D6AE, 0, { 0x0003B7 }},           /* 1D6AE; 03B7; Additional folding */
+  { 0x01D6AF, 0, { 0x0003B8 }},           /* 1D6AF; 03B8; Additional folding */
+  { 0x01D6B0, 0, { 0x0003B9 }},           /* 1D6B0; 03B9; Additional folding */
+  { 0x01D6B1, 0, { 0x0003BA }},           /* 1D6B1; 03BA; Additional folding */
+  { 0x01D6B2, 0, { 0x0003BB }},           /* 1D6B2; 03BB; Additional folding */
+  { 0x01D6B3, 0, { 0x0003BC }},           /* 1D6B3; 03BC; Additional folding */
+  { 0x01D6B4, 0, { 0x0003BD }},           /* 1D6B4; 03BD; Additional folding */
+  { 0x01D6B5, 0, { 0x0003BE }},           /* 1D6B5; 03BE; Additional folding */
+  { 0x01D6B6, 0, { 0x0003BF }},           /* 1D6B6; 03BF; Additional folding */
+  { 0x01D6B7, 0, { 0x0003C0 }},           /* 1D6B7; 03C0; Additional folding */
+  { 0x01D6B8, 0, { 0x0003C1 }},           /* 1D6B8; 03C1; Additional folding */
+  { 0x01D6B9, 0, { 0x0003B8 }},           /* 1D6B9; 03B8; Additional folding */
+  { 0x01D6BA, 0, { 0x0003C3 }},           /* 1D6BA; 03C3; Additional folding */
+  { 0x01D6BB, 0, { 0x0003C4 }},           /* 1D6BB; 03C4; Additional folding */
+  { 0x01D6BC, 0, { 0x0003C5 }},           /* 1D6BC; 03C5; Additional folding */
+  { 0x01D6BD, 0, { 0x0003C6 }},           /* 1D6BD; 03C6; Additional folding */
+  { 0x01D6BE, 0, { 0x0003C7 }},           /* 1D6BE; 03C7; Additional folding */
+  { 0x01D6BF, 0, { 0x0003C8 }},           /* 1D6BF; 03C8; Additional folding */
+  { 0x01D6C0, 0, { 0x0003C9 }},           /* 1D6C0; 03C9; Additional folding */
+  { 0x01D6D3, 0, { 0x0003C3 }},           /* 1D6D3; 03C3; Additional folding */
+  { 0x01D6E2, 0, { 0x0003B1 }},           /* 1D6E2; 03B1; Additional folding */
+  { 0x01D6E3, 0, { 0x0003B2 }},           /* 1D6E3; 03B2; Additional folding */
+  { 0x01D6E4, 0, { 0x0003B3 }},           /* 1D6E4; 03B3; Additional folding */
+  { 0x01D6E5, 0, { 0x0003B4 }},           /* 1D6E5; 03B4; Additional folding */
+  { 0x01D6E6, 0, { 0x0003B5 }},           /* 1D6E6; 03B5; Additional folding */
+  { 0x01D6E7, 0, { 0x0003B6 }},           /* 1D6E7; 03B6; Additional folding */
+  { 0x01D6E8, 0, { 0x0003B7 }},           /* 1D6E8; 03B7; Additional folding */
+  { 0x01D6E9, 0, { 0x0003B8 }},           /* 1D6E9; 03B8; Additional folding */
+  { 0x01D6EA, 0, { 0x0003B9 }},           /* 1D6EA; 03B9; Additional folding */
+  { 0x01D6EB, 0, { 0x0003BA }},           /* 1D6EB; 03BA; Additional folding */
+  { 0x01D6EC, 0, { 0x0003BB }},           /* 1D6EC; 03BB; Additional folding */
+  { 0x01D6ED, 0, { 0x0003BC }},           /* 1D6ED; 03BC; Additional folding */
+  { 0x01D6EE, 0, { 0x0003BD }},           /* 1D6EE; 03BD; Additional folding */
+  { 0x01D6EF, 0, { 0x0003BE }},           /* 1D6EF; 03BE; Additional folding */
+  { 0x01D6F0, 0, { 0x0003BF }},           /* 1D6F0; 03BF; Additional folding */
+  { 0x01D6F1, 0, { 0x0003C0 }},           /* 1D6F1; 03C0; Additional folding */
+  { 0x01D6F2, 0, { 0x0003C1 }},           /* 1D6F2; 03C1; Additional folding */
+  { 0x01D6F3, 0, { 0x0003B8 }},           /* 1D6F3; 03B8; Additional folding */
+  { 0x01D6F4, 0, { 0x0003C3 }},           /* 1D6F4; 03C3; Additional folding */
+  { 0x01D6F5, 0, { 0x0003C4 }},           /* 1D6F5; 03C4; Additional folding */
+  { 0x01D6F6, 0, { 0x0003C5 }},           /* 1D6F6; 03C5; Additional folding */
+  { 0x01D6F7, 0, { 0x0003C6 }},           /* 1D6F7; 03C6; Additional folding */
+  { 0x01D6F8, 0, { 0x0003C7 }},           /* 1D6F8; 03C7; Additional folding */
+  { 0x01D6F9, 0, { 0x0003C8 }},           /* 1D6F9; 03C8; Additional folding */
+  { 0x01D6FA, 0, { 0x0003C9 }},           /* 1D6FA; 03C9; Additional folding */
+  { 0x01D70D, 0, { 0x0003C3 }},           /* 1D70D; 03C3; Additional folding */
+  { 0x01D71C, 0, { 0x0003B1 }},           /* 1D71C; 03B1; Additional folding */
+  { 0x01D71D, 0, { 0x0003B2 }},           /* 1D71D; 03B2; Additional folding */
+  { 0x01D71E, 0, { 0x0003B3 }},           /* 1D71E; 03B3; Additional folding */
+  { 0x01D71F, 0, { 0x0003B4 }},           /* 1D71F; 03B4; Additional folding */
+  { 0x01D720, 0, { 0x0003B5 }},           /* 1D720; 03B5; Additional folding */
+  { 0x01D721, 0, { 0x0003B6 }},           /* 1D721; 03B6; Additional folding */
+  { 0x01D722, 0, { 0x0003B7 }},           /* 1D722; 03B7; Additional folding */
+  { 0x01D723, 0, { 0x0003B8 }},           /* 1D723; 03B8; Additional folding */
+  { 0x01D724, 0, { 0x0003B9 }},           /* 1D724; 03B9; Additional folding */
+  { 0x01D725, 0, { 0x0003BA }},           /* 1D725; 03BA; Additional folding */
+  { 0x01D726, 0, { 0x0003BB }},           /* 1D726; 03BB; Additional folding */
+  { 0x01D727, 0, { 0x0003BC }},           /* 1D727; 03BC; Additional folding */
+  { 0x01D728, 0, { 0x0003BD }},           /* 1D728; 03BD; Additional folding */
+  { 0x01D729, 0, { 0x0003BE }},           /* 1D729; 03BE; Additional folding */
+  { 0x01D72A, 0, { 0x0003BF }},           /* 1D72A; 03BF; Additional folding */
+  { 0x01D72B, 0, { 0x0003C0 }},           /* 1D72B; 03C0; Additional folding */
+  { 0x01D72C, 0, { 0x0003C1 }},           /* 1D72C; 03C1; Additional folding */
+  { 0x01D72D, 0, { 0x0003B8 }},           /* 1D72D; 03B8; Additional folding */
+  { 0x01D72E, 0, { 0x0003C3 }},           /* 1D72E; 03C3; Additional folding */
+  { 0x01D72F, 0, { 0x0003C4 }},           /* 1D72F; 03C4; Additional folding */
+  { 0x01D730, 0, { 0x0003C5 }},           /* 1D730; 03C5; Additional folding */
+  { 0x01D731, 0, { 0x0003C6 }},           /* 1D731; 03C6; Additional folding */
+  { 0x01D732, 0, { 0x0003C7 }},           /* 1D732; 03C7; Additional folding */
+  { 0x01D733, 0, { 0x0003C8 }},           /* 1D733; 03C8; Additional folding */
+  { 0x01D734, 0, { 0x0003C9 }},           /* 1D734; 03C9; Additional folding */
+  { 0x01D747, 0, { 0x0003C3 }},           /* 1D747; 03C3; Additional folding */
+  { 0x01D756, 0, { 0x0003B1 }},           /* 1D756; 03B1; Additional folding */
+  { 0x01D757, 0, { 0x0003B2 }},           /* 1D757; 03B2; Additional folding */
+  { 0x01D758, 0, { 0x0003B3 }},           /* 1D758; 03B3; Additional folding */
+  { 0x01D759, 0, { 0x0003B4 }},           /* 1D759; 03B4; Additional folding */
+  { 0x01D75A, 0, { 0x0003B5 }},           /* 1D75A; 03B5; Additional folding */
+  { 0x01D75B, 0, { 0x0003B6 }},           /* 1D75B; 03B6; Additional folding */
+  { 0x01D75C, 0, { 0x0003B7 }},           /* 1D75C; 03B7; Additional folding */
+  { 0x01D75D, 0, { 0x0003B8 }},           /* 1D75D; 03B8; Additional folding */
+  { 0x01D75E, 0, { 0x0003B9 }},           /* 1D75E; 03B9; Additional folding */
+  { 0x01D75F, 0, { 0x0003BA }},           /* 1D75F; 03BA; Additional folding */
+  { 0x01D760, 0, { 0x0003BB }},           /* 1D760; 03BB; Additional folding */
+  { 0x01D761, 0, { 0x0003BC }},           /* 1D761; 03BC; Additional folding */
+  { 0x01D762, 0, { 0x0003BD }},           /* 1D762; 03BD; Additional folding */
+  { 0x01D763, 0, { 0x0003BE }},           /* 1D763; 03BE; Additional folding */
+  { 0x01D764, 0, { 0x0003BF }},           /* 1D764; 03BF; Additional folding */
+  { 0x01D765, 0, { 0x0003C0 }},           /* 1D765; 03C0; Additional folding */
+  { 0x01D766, 0, { 0x0003C1 }},           /* 1D766; 03C1; Additional folding */
+  { 0x01D767, 0, { 0x0003B8 }},           /* 1D767; 03B8; Additional folding */
+  { 0x01D768, 0, { 0x0003C3 }},           /* 1D768; 03C3; Additional folding */
+  { 0x01D769, 0, { 0x0003C4 }},           /* 1D769; 03C4; Additional folding */
+  { 0x01D76A, 0, { 0x0003C5 }},           /* 1D76A; 03C5; Additional folding */
+  { 0x01D76B, 0, { 0x0003C6 }},           /* 1D76B; 03C6; Additional folding */
+  { 0x01D76C, 0, { 0x0003C7 }},           /* 1D76C; 03C7; Additional folding */
+  { 0x01D76D, 0, { 0x0003C8 }},           /* 1D76D; 03C8; Additional folding */
+  { 0x01D76E, 0, { 0x0003C9 }},           /* 1D76E; 03C9; Additional folding */
+  { 0x01D781, 0, { 0x0003C3 }},           /* 1D781; 03C3; Additional folding */
+  { 0x01D790, 0, { 0x0003B1 }},           /* 1D790; 03B1; Additional folding */
+  { 0x01D791, 0, { 0x0003B2 }},           /* 1D791; 03B2; Additional folding */
+  { 0x01D792, 0, { 0x0003B3 }},           /* 1D792; 03B3; Additional folding */
+  { 0x01D793, 0, { 0x0003B4 }},           /* 1D793; 03B4; Additional folding */
+  { 0x01D794, 0, { 0x0003B5 }},           /* 1D794; 03B5; Additional folding */
+  { 0x01D795, 0, { 0x0003B6 }},           /* 1D795; 03B6; Additional folding */
+  { 0x01D796, 0, { 0x0003B7 }},           /* 1D796; 03B7; Additional folding */
+  { 0x01D797, 0, { 0x0003B8 }},           /* 1D797; 03B8; Additional folding */
+  { 0x01D798, 0, { 0x0003B9 }},           /* 1D798; 03B9; Additional folding */
+  { 0x01D799, 0, { 0x0003BA }},           /* 1D799; 03BA; Additional folding */
+  { 0x01D79A, 0, { 0x0003BB }},           /* 1D79A; 03BB; Additional folding */
+  { 0x01D79B, 0, { 0x0003BC }},           /* 1D79B; 03BC; Additional folding */
+  { 0x01D79C, 0, { 0x0003BD }},           /* 1D79C; 03BD; Additional folding */
+  { 0x01D79D, 0, { 0x0003BE }},           /* 1D79D; 03BE; Additional folding */
+  { 0x01D79E, 0, { 0x0003BF }},           /* 1D79E; 03BF; Additional folding */
+  { 0x01D79F, 0, { 0x0003C0 }},           /* 1D79F; 03C0; Additional folding */
+  { 0x01D7A0, 0, { 0x0003C1 }},           /* 1D7A0; 03C1; Additional folding */
+  { 0x01D7A1, 0, { 0x0003B8 }},           /* 1D7A1; 03B8; Additional folding */
+  { 0x01D7A2, 0, { 0x0003C3 }},           /* 1D7A2; 03C3; Additional folding */
+  { 0x01D7A3, 0, { 0x0003C4 }},           /* 1D7A3; 03C4; Additional folding */
+  { 0x01D7A4, 0, { 0x0003C5 }},           /* 1D7A4; 03C5; Additional folding */
+  { 0x01D7A5, 0, { 0x0003C6 }},           /* 1D7A5; 03C6; Additional folding */
+  { 0x01D7A6, 0, { 0x0003C7 }},           /* 1D7A6; 03C7; Additional folding */
+  { 0x01D7A7, 0, { 0x0003C8 }},           /* 1D7A7; 03C8; Additional folding */
+  { 0x01D7A8, 0, { 0x0003C9 }},           /* 1D7A8; 03C9; Additional folding */
+  { 0x01D7BB, 0, { 0x0003C3 }},           /* 1D7BB; 03C3; Additional folding */
+  { 0 },
+};
+
+
+/*
+ * B.3 Mapping for case-folding used with no normalization
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_B_3[] = {
+  { 0x000041, 0, { 0x000061 }},                      /* 0041; 0061; Case map */
+  { 0x000042, 0, { 0x000062 }},                      /* 0042; 0062; Case map */
+  { 0x000043, 0, { 0x000063 }},                      /* 0043; 0063; Case map */
+  { 0x000044, 0, { 0x000064 }},                      /* 0044; 0064; Case map */
+  { 0x000045, 0, { 0x000065 }},                      /* 0045; 0065; Case map */
+  { 0x000046, 0, { 0x000066 }},                      /* 0046; 0066; Case map */
+  { 0x000047, 0, { 0x000067 }},                      /* 0047; 0067; Case map */
+  { 0x000048, 0, { 0x000068 }},                      /* 0048; 0068; Case map */
+  { 0x000049, 0, { 0x000069 }},                      /* 0049; 0069; Case map */
+  { 0x00004A, 0, { 0x00006A }},                      /* 004A; 006A; Case map */
+  { 0x00004B, 0, { 0x00006B }},                      /* 004B; 006B; Case map */
+  { 0x00004C, 0, { 0x00006C }},                      /* 004C; 006C; Case map */
+  { 0x00004D, 0, { 0x00006D }},                      /* 004D; 006D; Case map */
+  { 0x00004E, 0, { 0x00006E }},                      /* 004E; 006E; Case map */
+  { 0x00004F, 0, { 0x00006F }},                      /* 004F; 006F; Case map */
+  { 0x000050, 0, { 0x000070 }},                      /* 0050; 0070; Case map */
+  { 0x000051, 0, { 0x000071 }},                      /* 0051; 0071; Case map */
+  { 0x000052, 0, { 0x000072 }},                      /* 0052; 0072; Case map */
+  { 0x000053, 0, { 0x000073 }},                      /* 0053; 0073; Case map */
+  { 0x000054, 0, { 0x000074 }},                      /* 0054; 0074; Case map */
+  { 0x000055, 0, { 0x000075 }},                      /* 0055; 0075; Case map */
+  { 0x000056, 0, { 0x000076 }},                      /* 0056; 0076; Case map */
+  { 0x000057, 0, { 0x000077 }},                      /* 0057; 0077; Case map */
+  { 0x000058, 0, { 0x000078 }},                      /* 0058; 0078; Case map */
+  { 0x000059, 0, { 0x000079 }},                      /* 0059; 0079; Case map */
+  { 0x00005A, 0, { 0x00007A }},                      /* 005A; 007A; Case map */
+  { 0x0000B5, 0, { 0x0003BC }},                      /* 00B5; 03BC; Case map */
+  { 0x0000C0, 0, { 0x0000E0 }},                      /* 00C0; 00E0; Case map */
+  { 0x0000C1, 0, { 0x0000E1 }},                      /* 00C1; 00E1; Case map */
+  { 0x0000C2, 0, { 0x0000E2 }},                      /* 00C2; 00E2; Case map */
+  { 0x0000C3, 0, { 0x0000E3 }},                      /* 00C3; 00E3; Case map */
+  { 0x0000C4, 0, { 0x0000E4 }},                      /* 00C4; 00E4; Case map */
+  { 0x0000C5, 0, { 0x0000E5 }},                      /* 00C5; 00E5; Case map */
+  { 0x0000C6, 0, { 0x0000E6 }},                      /* 00C6; 00E6; Case map */
+  { 0x0000C7, 0, { 0x0000E7 }},                      /* 00C7; 00E7; Case map */
+  { 0x0000C8, 0, { 0x0000E8 }},                      /* 00C8; 00E8; Case map */
+  { 0x0000C9, 0, { 0x0000E9 }},                      /* 00C9; 00E9; Case map */
+  { 0x0000CA, 0, { 0x0000EA }},                      /* 00CA; 00EA; Case map */
+  { 0x0000CB, 0, { 0x0000EB }},                      /* 00CB; 00EB; Case map */
+  { 0x0000CC, 0, { 0x0000EC }},                      /* 00CC; 00EC; Case map */
+  { 0x0000CD, 0, { 0x0000ED }},                      /* 00CD; 00ED; Case map */
+  { 0x0000CE, 0, { 0x0000EE }},                      /* 00CE; 00EE; Case map */
+  { 0x0000CF, 0, { 0x0000EF }},                      /* 00CF; 00EF; Case map */
+  { 0x0000D0, 0, { 0x0000F0 }},                      /* 00D0; 00F0; Case map */
+  { 0x0000D1, 0, { 0x0000F1 }},                      /* 00D1; 00F1; Case map */
+  { 0x0000D2, 0, { 0x0000F2 }},                      /* 00D2; 00F2; Case map */
+  { 0x0000D3, 0, { 0x0000F3 }},                      /* 00D3; 00F3; Case map */
+  { 0x0000D4, 0, { 0x0000F4 }},                      /* 00D4; 00F4; Case map */
+  { 0x0000D5, 0, { 0x0000F5 }},                      /* 00D5; 00F5; Case map */
+  { 0x0000D6, 0, { 0x0000F6 }},                      /* 00D6; 00F6; Case map */
+  { 0x0000D8, 0, { 0x0000F8 }},                      /* 00D8; 00F8; Case map */
+  { 0x0000D9, 0, { 0x0000F9 }},                      /* 00D9; 00F9; Case map */
+  { 0x0000DA, 0, { 0x0000FA }},                      /* 00DA; 00FA; Case map */
+  { 0x0000DB, 0, { 0x0000FB }},                      /* 00DB; 00FB; Case map */
+  { 0x0000DC, 0, { 0x0000FC }},                      /* 00DC; 00FC; Case map */
+  { 0x0000DD, 0, { 0x0000FD }},                      /* 00DD; 00FD; Case map */
+  { 0x0000DE, 0, { 0x0000FE }},                      /* 00DE; 00FE; Case map */
+  { 0x0000DF, 0, { 0x000073,                    /* 00DF; 0073 0073; Case map */
+                   0x000073 }},
+  { 0x000100, 0, { 0x000101 }},                      /* 0100; 0101; Case map */
+  { 0x000102, 0, { 0x000103 }},                      /* 0102; 0103; Case map */
+  { 0x000104, 0, { 0x000105 }},                      /* 0104; 0105; Case map */
+  { 0x000106, 0, { 0x000107 }},                      /* 0106; 0107; Case map */
+  { 0x000108, 0, { 0x000109 }},                      /* 0108; 0109; Case map */
+  { 0x00010A, 0, { 0x00010B }},                      /* 010A; 010B; Case map */
+  { 0x00010C, 0, { 0x00010D }},                      /* 010C; 010D; Case map */
+  { 0x00010E, 0, { 0x00010F }},                      /* 010E; 010F; Case map */
+  { 0x000110, 0, { 0x000111 }},                      /* 0110; 0111; Case map */
+  { 0x000112, 0, { 0x000113 }},                      /* 0112; 0113; Case map */
+  { 0x000114, 0, { 0x000115 }},                      /* 0114; 0115; Case map */
+  { 0x000116, 0, { 0x000117 }},                      /* 0116; 0117; Case map */
+  { 0x000118, 0, { 0x000119 }},                      /* 0118; 0119; Case map */
+  { 0x00011A, 0, { 0x00011B }},                      /* 011A; 011B; Case map */
+  { 0x00011C, 0, { 0x00011D }},                      /* 011C; 011D; Case map */
+  { 0x00011E, 0, { 0x00011F }},                      /* 011E; 011F; Case map */
+  { 0x000120, 0, { 0x000121 }},                      /* 0120; 0121; Case map */
+  { 0x000122, 0, { 0x000123 }},                      /* 0122; 0123; Case map */
+  { 0x000124, 0, { 0x000125 }},                      /* 0124; 0125; Case map */
+  { 0x000126, 0, { 0x000127 }},                      /* 0126; 0127; Case map */
+  { 0x000128, 0, { 0x000129 }},                      /* 0128; 0129; Case map */
+  { 0x00012A, 0, { 0x00012B }},                      /* 012A; 012B; Case map */
+  { 0x00012C, 0, { 0x00012D }},                      /* 012C; 012D; Case map */
+  { 0x00012E, 0, { 0x00012F }},                      /* 012E; 012F; Case map */
+  { 0x000130, 0, { 0x000069,                    /* 0130; 0069 0307; Case map */
+                   0x000307 }},
+  { 0x000132, 0, { 0x000133 }},                      /* 0132; 0133; Case map */
+  { 0x000134, 0, { 0x000135 }},                      /* 0134; 0135; Case map */
+  { 0x000136, 0, { 0x000137 }},                      /* 0136; 0137; Case map */
+  { 0x000139, 0, { 0x00013A }},                      /* 0139; 013A; Case map */
+  { 0x00013B, 0, { 0x00013C }},                      /* 013B; 013C; Case map */
+  { 0x00013D, 0, { 0x00013E }},                      /* 013D; 013E; Case map */
+  { 0x00013F, 0, { 0x000140 }},                      /* 013F; 0140; Case map */
+  { 0x000141, 0, { 0x000142 }},                      /* 0141; 0142; Case map */
+  { 0x000143, 0, { 0x000144 }},                      /* 0143; 0144; Case map */
+  { 0x000145, 0, { 0x000146 }},                      /* 0145; 0146; Case map */
+  { 0x000147, 0, { 0x000148 }},                      /* 0147; 0148; Case map */
+  { 0x000149, 0, { 0x0002BC,                    /* 0149; 02BC 006E; Case map */
+                   0x00006E }},
+  { 0x00014A, 0, { 0x00014B }},                      /* 014A; 014B; Case map */
+  { 0x00014C, 0, { 0x00014D }},                      /* 014C; 014D; Case map */
+  { 0x00014E, 0, { 0x00014F }},                      /* 014E; 014F; Case map */
+  { 0x000150, 0, { 0x000151 }},                      /* 0150; 0151; Case map */
+  { 0x000152, 0, { 0x000153 }},                      /* 0152; 0153; Case map */
+  { 0x000154, 0, { 0x000155 }},                      /* 0154; 0155; Case map */
+  { 0x000156, 0, { 0x000157 }},                      /* 0156; 0157; Case map */
+  { 0x000158, 0, { 0x000159 }},                      /* 0158; 0159; Case map */
+  { 0x00015A, 0, { 0x00015B }},                      /* 015A; 015B; Case map */
+  { 0x00015C, 0, { 0x00015D }},                      /* 015C; 015D; Case map */
+  { 0x00015E, 0, { 0x00015F }},                      /* 015E; 015F; Case map */
+  { 0x000160, 0, { 0x000161 }},                      /* 0160; 0161; Case map */
+  { 0x000162, 0, { 0x000163 }},                      /* 0162; 0163; Case map */
+  { 0x000164, 0, { 0x000165 }},                      /* 0164; 0165; Case map */
+  { 0x000166, 0, { 0x000167 }},                      /* 0166; 0167; Case map */
+  { 0x000168, 0, { 0x000169 }},                      /* 0168; 0169; Case map */
+  { 0x00016A, 0, { 0x00016B }},                      /* 016A; 016B; Case map */
+  { 0x00016C, 0, { 0x00016D }},                      /* 016C; 016D; Case map */
+  { 0x00016E, 0, { 0x00016F }},                      /* 016E; 016F; Case map */
+  { 0x000170, 0, { 0x000171 }},                      /* 0170; 0171; Case map */
+  { 0x000172, 0, { 0x000173 }},                      /* 0172; 0173; Case map */
+  { 0x000174, 0, { 0x000175 }},                      /* 0174; 0175; Case map */
+  { 0x000176, 0, { 0x000177 }},                      /* 0176; 0177; Case map */
+  { 0x000178, 0, { 0x0000FF }},                      /* 0178; 00FF; Case map */
+  { 0x000179, 0, { 0x00017A }},                      /* 0179; 017A; Case map */
+  { 0x00017B, 0, { 0x00017C }},                      /* 017B; 017C; Case map */
+  { 0x00017D, 0, { 0x00017E }},                      /* 017D; 017E; Case map */
+  { 0x00017F, 0, { 0x000073 }},                      /* 017F; 0073; Case map */
+  { 0x000181, 0, { 0x000253 }},                      /* 0181; 0253; Case map */
+  { 0x000182, 0, { 0x000183 }},                      /* 0182; 0183; Case map */
+  { 0x000184, 0, { 0x000185 }},                      /* 0184; 0185; Case map */
+  { 0x000186, 0, { 0x000254 }},                      /* 0186; 0254; Case map */
+  { 0x000187, 0, { 0x000188 }},                      /* 0187; 0188; Case map */
+  { 0x000189, 0, { 0x000256 }},                      /* 0189; 0256; Case map */
+  { 0x00018A, 0, { 0x000257 }},                      /* 018A; 0257; Case map */
+  { 0x00018B, 0, { 0x00018C }},                      /* 018B; 018C; Case map */
+  { 0x00018E, 0, { 0x0001DD }},                      /* 018E; 01DD; Case map */
+  { 0x00018F, 0, { 0x000259 }},                      /* 018F; 0259; Case map */
+  { 0x000190, 0, { 0x00025B }},                      /* 0190; 025B; Case map */
+  { 0x000191, 0, { 0x000192 }},                      /* 0191; 0192; Case map */
+  { 0x000193, 0, { 0x000260 }},                      /* 0193; 0260; Case map */
+  { 0x000194, 0, { 0x000263 }},                      /* 0194; 0263; Case map */
+  { 0x000196, 0, { 0x000269 }},                      /* 0196; 0269; Case map */
+  { 0x000197, 0, { 0x000268 }},                      /* 0197; 0268; Case map */
+  { 0x000198, 0, { 0x000199 }},                      /* 0198; 0199; Case map */
+  { 0x00019C, 0, { 0x00026F }},                      /* 019C; 026F; Case map */
+  { 0x00019D, 0, { 0x000272 }},                      /* 019D; 0272; Case map */
+  { 0x00019F, 0, { 0x000275 }},                      /* 019F; 0275; Case map */
+  { 0x0001A0, 0, { 0x0001A1 }},                      /* 01A0; 01A1; Case map */
+  { 0x0001A2, 0, { 0x0001A3 }},                      /* 01A2; 01A3; Case map */
+  { 0x0001A4, 0, { 0x0001A5 }},                      /* 01A4; 01A5; Case map */
+  { 0x0001A6, 0, { 0x000280 }},                      /* 01A6; 0280; Case map */
+  { 0x0001A7, 0, { 0x0001A8 }},                      /* 01A7; 01A8; Case map */
+  { 0x0001A9, 0, { 0x000283 }},                      /* 01A9; 0283; Case map */
+  { 0x0001AC, 0, { 0x0001AD }},                      /* 01AC; 01AD; Case map */
+  { 0x0001AE, 0, { 0x000288 }},                      /* 01AE; 0288; Case map */
+  { 0x0001AF, 0, { 0x0001B0 }},                      /* 01AF; 01B0; Case map */
+  { 0x0001B1, 0, { 0x00028A }},                      /* 01B1; 028A; Case map */
+  { 0x0001B2, 0, { 0x00028B }},                      /* 01B2; 028B; Case map */
+  { 0x0001B3, 0, { 0x0001B4 }},                      /* 01B3; 01B4; Case map */
+  { 0x0001B5, 0, { 0x0001B6 }},                      /* 01B5; 01B6; Case map */
+  { 0x0001B7, 0, { 0x000292 }},                      /* 01B7; 0292; Case map */
+  { 0x0001B8, 0, { 0x0001B9 }},                      /* 01B8; 01B9; Case map */
+  { 0x0001BC, 0, { 0x0001BD }},                      /* 01BC; 01BD; Case map */
+  { 0x0001C4, 0, { 0x0001C6 }},                      /* 01C4; 01C6; Case map */
+  { 0x0001C5, 0, { 0x0001C6 }},                      /* 01C5; 01C6; Case map */
+  { 0x0001C7, 0, { 0x0001C9 }},                      /* 01C7; 01C9; Case map */
+  { 0x0001C8, 0, { 0x0001C9 }},                      /* 01C8; 01C9; Case map */
+  { 0x0001CA, 0, { 0x0001CC }},                      /* 01CA; 01CC; Case map */
+  { 0x0001CB, 0, { 0x0001CC }},                      /* 01CB; 01CC; Case map */
+  { 0x0001CD, 0, { 0x0001CE }},                      /* 01CD; 01CE; Case map */
+  { 0x0001CF, 0, { 0x0001D0 }},                      /* 01CF; 01D0; Case map */
+  { 0x0001D1, 0, { 0x0001D2 }},                      /* 01D1; 01D2; Case map */
+  { 0x0001D3, 0, { 0x0001D4 }},                      /* 01D3; 01D4; Case map */
+  { 0x0001D5, 0, { 0x0001D6 }},                      /* 01D5; 01D6; Case map */
+  { 0x0001D7, 0, { 0x0001D8 }},                      /* 01D7; 01D8; Case map */
+  { 0x0001D9, 0, { 0x0001DA }},                      /* 01D9; 01DA; Case map */
+  { 0x0001DB, 0, { 0x0001DC }},                      /* 01DB; 01DC; Case map */
+  { 0x0001DE, 0, { 0x0001DF }},                      /* 01DE; 01DF; Case map */
+  { 0x0001E0, 0, { 0x0001E1 }},                      /* 01E0; 01E1; Case map */
+  { 0x0001E2, 0, { 0x0001E3 }},                      /* 01E2; 01E3; Case map */
+  { 0x0001E4, 0, { 0x0001E5 }},                      /* 01E4; 01E5; Case map */
+  { 0x0001E6, 0, { 0x0001E7 }},                      /* 01E6; 01E7; Case map */
+  { 0x0001E8, 0, { 0x0001E9 }},                      /* 01E8; 01E9; Case map */
+  { 0x0001EA, 0, { 0x0001EB }},                      /* 01EA; 01EB; Case map */
+  { 0x0001EC, 0, { 0x0001ED }},                      /* 01EC; 01ED; Case map */
+  { 0x0001EE, 0, { 0x0001EF }},                      /* 01EE; 01EF; Case map */
+  { 0x0001F0, 0, { 0x00006A,                    /* 01F0; 006A 030C; Case map */
+                   0x00030C }},
+  { 0x0001F1, 0, { 0x0001F3 }},                      /* 01F1; 01F3; Case map */
+  { 0x0001F2, 0, { 0x0001F3 }},                      /* 01F2; 01F3; Case map */
+  { 0x0001F4, 0, { 0x0001F5 }},                      /* 01F4; 01F5; Case map */
+  { 0x0001F6, 0, { 0x000195 }},                      /* 01F6; 0195; Case map */
+  { 0x0001F7, 0, { 0x0001BF }},                      /* 01F7; 01BF; Case map */
+  { 0x0001F8, 0, { 0x0001F9 }},                      /* 01F8; 01F9; Case map */
+  { 0x0001FA, 0, { 0x0001FB }},                      /* 01FA; 01FB; Case map */
+  { 0x0001FC, 0, { 0x0001FD }},                      /* 01FC; 01FD; Case map */
+  { 0x0001FE, 0, { 0x0001FF }},                      /* 01FE; 01FF; Case map */
+  { 0x000200, 0, { 0x000201 }},                      /* 0200; 0201; Case map */
+  { 0x000202, 0, { 0x000203 }},                      /* 0202; 0203; Case map */
+  { 0x000204, 0, { 0x000205 }},                      /* 0204; 0205; Case map */
+  { 0x000206, 0, { 0x000207 }},                      /* 0206; 0207; Case map */
+  { 0x000208, 0, { 0x000209 }},                      /* 0208; 0209; Case map */
+  { 0x00020A, 0, { 0x00020B }},                      /* 020A; 020B; Case map */
+  { 0x00020C, 0, { 0x00020D }},                      /* 020C; 020D; Case map */
+  { 0x00020E, 0, { 0x00020F }},                      /* 020E; 020F; Case map */
+  { 0x000210, 0, { 0x000211 }},                      /* 0210; 0211; Case map */
+  { 0x000212, 0, { 0x000213 }},                      /* 0212; 0213; Case map */
+  { 0x000214, 0, { 0x000215 }},                      /* 0214; 0215; Case map */
+  { 0x000216, 0, { 0x000217 }},                      /* 0216; 0217; Case map */
+  { 0x000218, 0, { 0x000219 }},                      /* 0218; 0219; Case map */
+  { 0x00021A, 0, { 0x00021B }},                      /* 021A; 021B; Case map */
+  { 0x00021C, 0, { 0x00021D }},                      /* 021C; 021D; Case map */
+  { 0x00021E, 0, { 0x00021F }},                      /* 021E; 021F; Case map */
+  { 0x000220, 0, { 0x00019E }},                      /* 0220; 019E; Case map */
+  { 0x000222, 0, { 0x000223 }},                      /* 0222; 0223; Case map */
+  { 0x000224, 0, { 0x000225 }},                      /* 0224; 0225; Case map */
+  { 0x000226, 0, { 0x000227 }},                      /* 0226; 0227; Case map */
+  { 0x000228, 0, { 0x000229 }},                      /* 0228; 0229; Case map */
+  { 0x00022A, 0, { 0x00022B }},                      /* 022A; 022B; Case map */
+  { 0x00022C, 0, { 0x00022D }},                      /* 022C; 022D; Case map */
+  { 0x00022E, 0, { 0x00022F }},                      /* 022E; 022F; Case map */
+  { 0x000230, 0, { 0x000231 }},                      /* 0230; 0231; Case map */
+  { 0x000232, 0, { 0x000233 }},                      /* 0232; 0233; Case map */
+  { 0x000345, 0, { 0x0003B9 }},                      /* 0345; 03B9; Case map */
+  { 0x000386, 0, { 0x0003AC }},                      /* 0386; 03AC; Case map */
+  { 0x000388, 0, { 0x0003AD }},                      /* 0388; 03AD; Case map */
+  { 0x000389, 0, { 0x0003AE }},                      /* 0389; 03AE; Case map */
+  { 0x00038A, 0, { 0x0003AF }},                      /* 038A; 03AF; Case map */
+  { 0x00038C, 0, { 0x0003CC }},                      /* 038C; 03CC; Case map */
+  { 0x00038E, 0, { 0x0003CD }},                      /* 038E; 03CD; Case map */
+  { 0x00038F, 0, { 0x0003CE }},                      /* 038F; 03CE; Case map */
+  { 0x000390, 0, { 0x0003B9,               /* 0390; 03B9 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x000391, 0, { 0x0003B1 }},                      /* 0391; 03B1; Case map */
+  { 0x000392, 0, { 0x0003B2 }},                      /* 0392; 03B2; Case map */
+  { 0x000393, 0, { 0x0003B3 }},                      /* 0393; 03B3; Case map */
+  { 0x000394, 0, { 0x0003B4 }},                      /* 0394; 03B4; Case map */
+  { 0x000395, 0, { 0x0003B5 }},                      /* 0395; 03B5; Case map */
+  { 0x000396, 0, { 0x0003B6 }},                      /* 0396; 03B6; Case map */
+  { 0x000397, 0, { 0x0003B7 }},                      /* 0397; 03B7; Case map */
+  { 0x000398, 0, { 0x0003B8 }},                      /* 0398; 03B8; Case map */
+  { 0x000399, 0, { 0x0003B9 }},                      /* 0399; 03B9; Case map */
+  { 0x00039A, 0, { 0x0003BA }},                      /* 039A; 03BA; Case map */
+  { 0x00039B, 0, { 0x0003BB }},                      /* 039B; 03BB; Case map */
+  { 0x00039C, 0, { 0x0003BC }},                      /* 039C; 03BC; Case map */
+  { 0x00039D, 0, { 0x0003BD }},                      /* 039D; 03BD; Case map */
+  { 0x00039E, 0, { 0x0003BE }},                      /* 039E; 03BE; Case map */
+  { 0x00039F, 0, { 0x0003BF }},                      /* 039F; 03BF; Case map */
+  { 0x0003A0, 0, { 0x0003C0 }},                      /* 03A0; 03C0; Case map */
+  { 0x0003A1, 0, { 0x0003C1 }},                      /* 03A1; 03C1; Case map */
+  { 0x0003A3, 0, { 0x0003C3 }},                      /* 03A3; 03C3; Case map */
+  { 0x0003A4, 0, { 0x0003C4 }},                      /* 03A4; 03C4; Case map */
+  { 0x0003A5, 0, { 0x0003C5 }},                      /* 03A5; 03C5; Case map */
+  { 0x0003A6, 0, { 0x0003C6 }},                      /* 03A6; 03C6; Case map */
+  { 0x0003A7, 0, { 0x0003C7 }},                      /* 03A7; 03C7; Case map */
+  { 0x0003A8, 0, { 0x0003C8 }},                      /* 03A8; 03C8; Case map */
+  { 0x0003A9, 0, { 0x0003C9 }},                      /* 03A9; 03C9; Case map */
+  { 0x0003AA, 0, { 0x0003CA }},                      /* 03AA; 03CA; Case map */
+  { 0x0003AB, 0, { 0x0003CB }},                      /* 03AB; 03CB; Case map */
+  { 0x0003B0, 0, { 0x0003C5,               /* 03B0; 03C5 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x0003C2, 0, { 0x0003C3 }},                      /* 03C2; 03C3; Case map */
+  { 0x0003D0, 0, { 0x0003B2 }},                      /* 03D0; 03B2; Case map */
+  { 0x0003D1, 0, { 0x0003B8 }},                      /* 03D1; 03B8; Case map */
+  { 0x0003D5, 0, { 0x0003C6 }},                      /* 03D5; 03C6; Case map */
+  { 0x0003D6, 0, { 0x0003C0 }},                      /* 03D6; 03C0; Case map */
+  { 0x0003D8, 0, { 0x0003D9 }},                      /* 03D8; 03D9; Case map */
+  { 0x0003DA, 0, { 0x0003DB }},                      /* 03DA; 03DB; Case map */
+  { 0x0003DC, 0, { 0x0003DD }},                      /* 03DC; 03DD; Case map */
+  { 0x0003DE, 0, { 0x0003DF }},                      /* 03DE; 03DF; Case map */
+  { 0x0003E0, 0, { 0x0003E1 }},                      /* 03E0; 03E1; Case map */
+  { 0x0003E2, 0, { 0x0003E3 }},                      /* 03E2; 03E3; Case map */
+  { 0x0003E4, 0, { 0x0003E5 }},                      /* 03E4; 03E5; Case map */
+  { 0x0003E6, 0, { 0x0003E7 }},                      /* 03E6; 03E7; Case map */
+  { 0x0003E8, 0, { 0x0003E9 }},                      /* 03E8; 03E9; Case map */
+  { 0x0003EA, 0, { 0x0003EB }},                      /* 03EA; 03EB; Case map */
+  { 0x0003EC, 0, { 0x0003ED }},                      /* 03EC; 03ED; Case map */
+  { 0x0003EE, 0, { 0x0003EF }},                      /* 03EE; 03EF; Case map */
+  { 0x0003F0, 0, { 0x0003BA }},                      /* 03F0; 03BA; Case map */
+  { 0x0003F1, 0, { 0x0003C1 }},                      /* 03F1; 03C1; Case map */
+  { 0x0003F2, 0, { 0x0003C3 }},                      /* 03F2; 03C3; Case map */
+  { 0x0003F4, 0, { 0x0003B8 }},                      /* 03F4; 03B8; Case map */
+  { 0x0003F5, 0, { 0x0003B5 }},                      /* 03F5; 03B5; Case map */
+  { 0x000400, 0, { 0x000450 }},                      /* 0400; 0450; Case map */
+  { 0x000401, 0, { 0x000451 }},                      /* 0401; 0451; Case map */
+  { 0x000402, 0, { 0x000452 }},                      /* 0402; 0452; Case map */
+  { 0x000403, 0, { 0x000453 }},                      /* 0403; 0453; Case map */
+  { 0x000404, 0, { 0x000454 }},                      /* 0404; 0454; Case map */
+  { 0x000405, 0, { 0x000455 }},                      /* 0405; 0455; Case map */
+  { 0x000406, 0, { 0x000456 }},                      /* 0406; 0456; Case map */
+  { 0x000407, 0, { 0x000457 }},                      /* 0407; 0457; Case map */
+  { 0x000408, 0, { 0x000458 }},                      /* 0408; 0458; Case map */
+  { 0x000409, 0, { 0x000459 }},                      /* 0409; 0459; Case map */
+  { 0x00040A, 0, { 0x00045A }},                      /* 040A; 045A; Case map */
+  { 0x00040B, 0, { 0x00045B }},                      /* 040B; 045B; Case map */
+  { 0x00040C, 0, { 0x00045C }},                      /* 040C; 045C; Case map */
+  { 0x00040D, 0, { 0x00045D }},                      /* 040D; 045D; Case map */
+  { 0x00040E, 0, { 0x00045E }},                      /* 040E; 045E; Case map */
+  { 0x00040F, 0, { 0x00045F }},                      /* 040F; 045F; Case map */
+  { 0x000410, 0, { 0x000430 }},                      /* 0410; 0430; Case map */
+  { 0x000411, 0, { 0x000431 }},                      /* 0411; 0431; Case map */
+  { 0x000412, 0, { 0x000432 }},                      /* 0412; 0432; Case map */
+  { 0x000413, 0, { 0x000433 }},                      /* 0413; 0433; Case map */
+  { 0x000414, 0, { 0x000434 }},                      /* 0414; 0434; Case map */
+  { 0x000415, 0, { 0x000435 }},                      /* 0415; 0435; Case map */
+  { 0x000416, 0, { 0x000436 }},                      /* 0416; 0436; Case map */
+  { 0x000417, 0, { 0x000437 }},                      /* 0417; 0437; Case map */
+  { 0x000418, 0, { 0x000438 }},                      /* 0418; 0438; Case map */
+  { 0x000419, 0, { 0x000439 }},                      /* 0419; 0439; Case map */
+  { 0x00041A, 0, { 0x00043A }},                      /* 041A; 043A; Case map */
+  { 0x00041B, 0, { 0x00043B }},                      /* 041B; 043B; Case map */
+  { 0x00041C, 0, { 0x00043C }},                      /* 041C; 043C; Case map */
+  { 0x00041D, 0, { 0x00043D }},                      /* 041D; 043D; Case map */
+  { 0x00041E, 0, { 0x00043E }},                      /* 041E; 043E; Case map */
+  { 0x00041F, 0, { 0x00043F }},                      /* 041F; 043F; Case map */
+  { 0x000420, 0, { 0x000440 }},                      /* 0420; 0440; Case map */
+  { 0x000421, 0, { 0x000441 }},                      /* 0421; 0441; Case map */
+  { 0x000422, 0, { 0x000442 }},                      /* 0422; 0442; Case map */
+  { 0x000423, 0, { 0x000443 }},                      /* 0423; 0443; Case map */
+  { 0x000424, 0, { 0x000444 }},                      /* 0424; 0444; Case map */
+  { 0x000425, 0, { 0x000445 }},                      /* 0425; 0445; Case map */
+  { 0x000426, 0, { 0x000446 }},                      /* 0426; 0446; Case map */
+  { 0x000427, 0, { 0x000447 }},                      /* 0427; 0447; Case map */
+  { 0x000428, 0, { 0x000448 }},                      /* 0428; 0448; Case map */
+  { 0x000429, 0, { 0x000449 }},                      /* 0429; 0449; Case map */
+  { 0x00042A, 0, { 0x00044A }},                      /* 042A; 044A; Case map */
+  { 0x00042B, 0, { 0x00044B }},                      /* 042B; 044B; Case map */
+  { 0x00042C, 0, { 0x00044C }},                      /* 042C; 044C; Case map */
+  { 0x00042D, 0, { 0x00044D }},                      /* 042D; 044D; Case map */
+  { 0x00042E, 0, { 0x00044E }},                      /* 042E; 044E; Case map */
+  { 0x00042F, 0, { 0x00044F }},                      /* 042F; 044F; Case map */
+  { 0x000460, 0, { 0x000461 }},                      /* 0460; 0461; Case map */
+  { 0x000462, 0, { 0x000463 }},                      /* 0462; 0463; Case map */
+  { 0x000464, 0, { 0x000465 }},                      /* 0464; 0465; Case map */
+  { 0x000466, 0, { 0x000467 }},                      /* 0466; 0467; Case map */
+  { 0x000468, 0, { 0x000469 }},                      /* 0468; 0469; Case map */
+  { 0x00046A, 0, { 0x00046B }},                      /* 046A; 046B; Case map */
+  { 0x00046C, 0, { 0x00046D }},                      /* 046C; 046D; Case map */
+  { 0x00046E, 0, { 0x00046F }},                      /* 046E; 046F; Case map */
+  { 0x000470, 0, { 0x000471 }},                      /* 0470; 0471; Case map */
+  { 0x000472, 0, { 0x000473 }},                      /* 0472; 0473; Case map */
+  { 0x000474, 0, { 0x000475 }},                      /* 0474; 0475; Case map */
+  { 0x000476, 0, { 0x000477 }},                      /* 0476; 0477; Case map */
+  { 0x000478, 0, { 0x000479 }},                      /* 0478; 0479; Case map */
+  { 0x00047A, 0, { 0x00047B }},                      /* 047A; 047B; Case map */
+  { 0x00047C, 0, { 0x00047D }},                      /* 047C; 047D; Case map */
+  { 0x00047E, 0, { 0x00047F }},                      /* 047E; 047F; Case map */
+  { 0x000480, 0, { 0x000481 }},                      /* 0480; 0481; Case map */
+  { 0x00048A, 0, { 0x00048B }},                      /* 048A; 048B; Case map */
+  { 0x00048C, 0, { 0x00048D }},                      /* 048C; 048D; Case map */
+  { 0x00048E, 0, { 0x00048F }},                      /* 048E; 048F; Case map */
+  { 0x000490, 0, { 0x000491 }},                      /* 0490; 0491; Case map */
+  { 0x000492, 0, { 0x000493 }},                      /* 0492; 0493; Case map */
+  { 0x000494, 0, { 0x000495 }},                      /* 0494; 0495; Case map */
+  { 0x000496, 0, { 0x000497 }},                      /* 0496; 0497; Case map */
+  { 0x000498, 0, { 0x000499 }},                      /* 0498; 0499; Case map */
+  { 0x00049A, 0, { 0x00049B }},                      /* 049A; 049B; Case map */
+  { 0x00049C, 0, { 0x00049D }},                      /* 049C; 049D; Case map */
+  { 0x00049E, 0, { 0x00049F }},                      /* 049E; 049F; Case map */
+  { 0x0004A0, 0, { 0x0004A1 }},                      /* 04A0; 04A1; Case map */
+  { 0x0004A2, 0, { 0x0004A3 }},                      /* 04A2; 04A3; Case map */
+  { 0x0004A4, 0, { 0x0004A5 }},                      /* 04A4; 04A5; Case map */
+  { 0x0004A6, 0, { 0x0004A7 }},                      /* 04A6; 04A7; Case map */
+  { 0x0004A8, 0, { 0x0004A9 }},                      /* 04A8; 04A9; Case map */
+  { 0x0004AA, 0, { 0x0004AB }},                      /* 04AA; 04AB; Case map */
+  { 0x0004AC, 0, { 0x0004AD }},                      /* 04AC; 04AD; Case map */
+  { 0x0004AE, 0, { 0x0004AF }},                      /* 04AE; 04AF; Case map */
+  { 0x0004B0, 0, { 0x0004B1 }},                      /* 04B0; 04B1; Case map */
+  { 0x0004B2, 0, { 0x0004B3 }},                      /* 04B2; 04B3; Case map */
+  { 0x0004B4, 0, { 0x0004B5 }},                      /* 04B4; 04B5; Case map */
+  { 0x0004B6, 0, { 0x0004B7 }},                      /* 04B6; 04B7; Case map */
+  { 0x0004B8, 0, { 0x0004B9 }},                      /* 04B8; 04B9; Case map */
+  { 0x0004BA, 0, { 0x0004BB }},                      /* 04BA; 04BB; Case map */
+  { 0x0004BC, 0, { 0x0004BD }},                      /* 04BC; 04BD; Case map */
+  { 0x0004BE, 0, { 0x0004BF }},                      /* 04BE; 04BF; Case map */
+  { 0x0004C1, 0, { 0x0004C2 }},                      /* 04C1; 04C2; Case map */
+  { 0x0004C3, 0, { 0x0004C4 }},                      /* 04C3; 04C4; Case map */
+  { 0x0004C5, 0, { 0x0004C6 }},                      /* 04C5; 04C6; Case map */
+  { 0x0004C7, 0, { 0x0004C8 }},                      /* 04C7; 04C8; Case map */
+  { 0x0004C9, 0, { 0x0004CA }},                      /* 04C9; 04CA; Case map */
+  { 0x0004CB, 0, { 0x0004CC }},                      /* 04CB; 04CC; Case map */
+  { 0x0004CD, 0, { 0x0004CE }},                      /* 04CD; 04CE; Case map */
+  { 0x0004D0, 0, { 0x0004D1 }},                      /* 04D0; 04D1; Case map */
+  { 0x0004D2, 0, { 0x0004D3 }},                      /* 04D2; 04D3; Case map */
+  { 0x0004D4, 0, { 0x0004D5 }},                      /* 04D4; 04D5; Case map */
+  { 0x0004D6, 0, { 0x0004D7 }},                      /* 04D6; 04D7; Case map */
+  { 0x0004D8, 0, { 0x0004D9 }},                      /* 04D8; 04D9; Case map */
+  { 0x0004DA, 0, { 0x0004DB }},                      /* 04DA; 04DB; Case map */
+  { 0x0004DC, 0, { 0x0004DD }},                      /* 04DC; 04DD; Case map */
+  { 0x0004DE, 0, { 0x0004DF }},                      /* 04DE; 04DF; Case map */
+  { 0x0004E0, 0, { 0x0004E1 }},                      /* 04E0; 04E1; Case map */
+  { 0x0004E2, 0, { 0x0004E3 }},                      /* 04E2; 04E3; Case map */
+  { 0x0004E4, 0, { 0x0004E5 }},                      /* 04E4; 04E5; Case map */
+  { 0x0004E6, 0, { 0x0004E7 }},                      /* 04E6; 04E7; Case map */
+  { 0x0004E8, 0, { 0x0004E9 }},                      /* 04E8; 04E9; Case map */
+  { 0x0004EA, 0, { 0x0004EB }},                      /* 04EA; 04EB; Case map */
+  { 0x0004EC, 0, { 0x0004ED }},                      /* 04EC; 04ED; Case map */
+  { 0x0004EE, 0, { 0x0004EF }},                      /* 04EE; 04EF; Case map */
+  { 0x0004F0, 0, { 0x0004F1 }},                      /* 04F0; 04F1; Case map */
+  { 0x0004F2, 0, { 0x0004F3 }},                      /* 04F2; 04F3; Case map */
+  { 0x0004F4, 0, { 0x0004F5 }},                      /* 04F4; 04F5; Case map */
+  { 0x0004F8, 0, { 0x0004F9 }},                      /* 04F8; 04F9; Case map */
+  { 0x000500, 0, { 0x000501 }},                      /* 0500; 0501; Case map */
+  { 0x000502, 0, { 0x000503 }},                      /* 0502; 0503; Case map */
+  { 0x000504, 0, { 0x000505 }},                      /* 0504; 0505; Case map */
+  { 0x000506, 0, { 0x000507 }},                      /* 0506; 0507; Case map */
+  { 0x000508, 0, { 0x000509 }},                      /* 0508; 0509; Case map */
+  { 0x00050A, 0, { 0x00050B }},                      /* 050A; 050B; Case map */
+  { 0x00050C, 0, { 0x00050D }},                      /* 050C; 050D; Case map */
+  { 0x00050E, 0, { 0x00050F }},                      /* 050E; 050F; Case map */
+  { 0x000531, 0, { 0x000561 }},                      /* 0531; 0561; Case map */
+  { 0x000532, 0, { 0x000562 }},                      /* 0532; 0562; Case map */
+  { 0x000533, 0, { 0x000563 }},                      /* 0533; 0563; Case map */
+  { 0x000534, 0, { 0x000564 }},                      /* 0534; 0564; Case map */
+  { 0x000535, 0, { 0x000565 }},                      /* 0535; 0565; Case map */
+  { 0x000536, 0, { 0x000566 }},                      /* 0536; 0566; Case map */
+  { 0x000537, 0, { 0x000567 }},                      /* 0537; 0567; Case map */
+  { 0x000538, 0, { 0x000568 }},                      /* 0538; 0568; Case map */
+  { 0x000539, 0, { 0x000569 }},                      /* 0539; 0569; Case map */
+  { 0x00053A, 0, { 0x00056A }},                      /* 053A; 056A; Case map */
+  { 0x00053B, 0, { 0x00056B }},                      /* 053B; 056B; Case map */
+  { 0x00053C, 0, { 0x00056C }},                      /* 053C; 056C; Case map */
+  { 0x00053D, 0, { 0x00056D }},                      /* 053D; 056D; Case map */
+  { 0x00053E, 0, { 0x00056E }},                      /* 053E; 056E; Case map */
+  { 0x00053F, 0, { 0x00056F }},                      /* 053F; 056F; Case map */
+  { 0x000540, 0, { 0x000570 }},                      /* 0540; 0570; Case map */
+  { 0x000541, 0, { 0x000571 }},                      /* 0541; 0571; Case map */
+  { 0x000542, 0, { 0x000572 }},                      /* 0542; 0572; Case map */
+  { 0x000543, 0, { 0x000573 }},                      /* 0543; 0573; Case map */
+  { 0x000544, 0, { 0x000574 }},                      /* 0544; 0574; Case map */
+  { 0x000545, 0, { 0x000575 }},                      /* 0545; 0575; Case map */
+  { 0x000546, 0, { 0x000576 }},                      /* 0546; 0576; Case map */
+  { 0x000547, 0, { 0x000577 }},                      /* 0547; 0577; Case map */
+  { 0x000548, 0, { 0x000578 }},                      /* 0548; 0578; Case map */
+  { 0x000549, 0, { 0x000579 }},                      /* 0549; 0579; Case map */
+  { 0x00054A, 0, { 0x00057A }},                      /* 054A; 057A; Case map */
+  { 0x00054B, 0, { 0x00057B }},                      /* 054B; 057B; Case map */
+  { 0x00054C, 0, { 0x00057C }},                      /* 054C; 057C; Case map */
+  { 0x00054D, 0, { 0x00057D }},                      /* 054D; 057D; Case map */
+  { 0x00054E, 0, { 0x00057E }},                      /* 054E; 057E; Case map */
+  { 0x00054F, 0, { 0x00057F }},                      /* 054F; 057F; Case map */
+  { 0x000550, 0, { 0x000580 }},                      /* 0550; 0580; Case map */
+  { 0x000551, 0, { 0x000581 }},                      /* 0551; 0581; Case map */
+  { 0x000552, 0, { 0x000582 }},                      /* 0552; 0582; Case map */
+  { 0x000553, 0, { 0x000583 }},                      /* 0553; 0583; Case map */
+  { 0x000554, 0, { 0x000584 }},                      /* 0554; 0584; Case map */
+  { 0x000555, 0, { 0x000585 }},                      /* 0555; 0585; Case map */
+  { 0x000556, 0, { 0x000586 }},                      /* 0556; 0586; Case map */
+  { 0x000587, 0, { 0x000565,                    /* 0587; 0565 0582; Case map */
+                   0x000582 }},
+  { 0x001E00, 0, { 0x001E01 }},                      /* 1E00; 1E01; Case map */
+  { 0x001E02, 0, { 0x001E03 }},                      /* 1E02; 1E03; Case map */
+  { 0x001E04, 0, { 0x001E05 }},                      /* 1E04; 1E05; Case map */
+  { 0x001E06, 0, { 0x001E07 }},                      /* 1E06; 1E07; Case map */
+  { 0x001E08, 0, { 0x001E09 }},                      /* 1E08; 1E09; Case map */
+  { 0x001E0A, 0, { 0x001E0B }},                      /* 1E0A; 1E0B; Case map */
+  { 0x001E0C, 0, { 0x001E0D }},                      /* 1E0C; 1E0D; Case map */
+  { 0x001E0E, 0, { 0x001E0F }},                      /* 1E0E; 1E0F; Case map */
+  { 0x001E10, 0, { 0x001E11 }},                      /* 1E10; 1E11; Case map */
+  { 0x001E12, 0, { 0x001E13 }},                      /* 1E12; 1E13; Case map */
+  { 0x001E14, 0, { 0x001E15 }},                      /* 1E14; 1E15; Case map */
+  { 0x001E16, 0, { 0x001E17 }},                      /* 1E16; 1E17; Case map */
+  { 0x001E18, 0, { 0x001E19 }},                      /* 1E18; 1E19; Case map */
+  { 0x001E1A, 0, { 0x001E1B }},                      /* 1E1A; 1E1B; Case map */
+  { 0x001E1C, 0, { 0x001E1D }},                      /* 1E1C; 1E1D; Case map */
+  { 0x001E1E, 0, { 0x001E1F }},                      /* 1E1E; 1E1F; Case map */
+  { 0x001E20, 0, { 0x001E21 }},                      /* 1E20; 1E21; Case map */
+  { 0x001E22, 0, { 0x001E23 }},                      /* 1E22; 1E23; Case map */
+  { 0x001E24, 0, { 0x001E25 }},                      /* 1E24; 1E25; Case map */
+  { 0x001E26, 0, { 0x001E27 }},                      /* 1E26; 1E27; Case map */
+  { 0x001E28, 0, { 0x001E29 }},                      /* 1E28; 1E29; Case map */
+  { 0x001E2A, 0, { 0x001E2B }},                      /* 1E2A; 1E2B; Case map */
+  { 0x001E2C, 0, { 0x001E2D }},                      /* 1E2C; 1E2D; Case map */
+  { 0x001E2E, 0, { 0x001E2F }},                      /* 1E2E; 1E2F; Case map */
+  { 0x001E30, 0, { 0x001E31 }},                      /* 1E30; 1E31; Case map */
+  { 0x001E32, 0, { 0x001E33 }},                      /* 1E32; 1E33; Case map */
+  { 0x001E34, 0, { 0x001E35 }},                      /* 1E34; 1E35; Case map */
+  { 0x001E36, 0, { 0x001E37 }},                      /* 1E36; 1E37; Case map */
+  { 0x001E38, 0, { 0x001E39 }},                      /* 1E38; 1E39; Case map */
+  { 0x001E3A, 0, { 0x001E3B }},                      /* 1E3A; 1E3B; Case map */
+  { 0x001E3C, 0, { 0x001E3D }},                      /* 1E3C; 1E3D; Case map */
+  { 0x001E3E, 0, { 0x001E3F }},                      /* 1E3E; 1E3F; Case map */
+  { 0x001E40, 0, { 0x001E41 }},                      /* 1E40; 1E41; Case map */
+  { 0x001E42, 0, { 0x001E43 }},                      /* 1E42; 1E43; Case map */
+  { 0x001E44, 0, { 0x001E45 }},                      /* 1E44; 1E45; Case map */
+  { 0x001E46, 0, { 0x001E47 }},                      /* 1E46; 1E47; Case map */
+  { 0x001E48, 0, { 0x001E49 }},                      /* 1E48; 1E49; Case map */
+  { 0x001E4A, 0, { 0x001E4B }},                      /* 1E4A; 1E4B; Case map */
+  { 0x001E4C, 0, { 0x001E4D }},                      /* 1E4C; 1E4D; Case map */
+  { 0x001E4E, 0, { 0x001E4F }},                      /* 1E4E; 1E4F; Case map */
+  { 0x001E50, 0, { 0x001E51 }},                      /* 1E50; 1E51; Case map */
+  { 0x001E52, 0, { 0x001E53 }},                      /* 1E52; 1E53; Case map */
+  { 0x001E54, 0, { 0x001E55 }},                      /* 1E54; 1E55; Case map */
+  { 0x001E56, 0, { 0x001E57 }},                      /* 1E56; 1E57; Case map */
+  { 0x001E58, 0, { 0x001E59 }},                      /* 1E58; 1E59; Case map */
+  { 0x001E5A, 0, { 0x001E5B }},                      /* 1E5A; 1E5B; Case map */
+  { 0x001E5C, 0, { 0x001E5D }},                      /* 1E5C; 1E5D; Case map */
+  { 0x001E5E, 0, { 0x001E5F }},                      /* 1E5E; 1E5F; Case map */
+  { 0x001E60, 0, { 0x001E61 }},                      /* 1E60; 1E61; Case map */
+  { 0x001E62, 0, { 0x001E63 }},                      /* 1E62; 1E63; Case map */
+  { 0x001E64, 0, { 0x001E65 }},                      /* 1E64; 1E65; Case map */
+  { 0x001E66, 0, { 0x001E67 }},                      /* 1E66; 1E67; Case map */
+  { 0x001E68, 0, { 0x001E69 }},                      /* 1E68; 1E69; Case map */
+  { 0x001E6A, 0, { 0x001E6B }},                      /* 1E6A; 1E6B; Case map */
+  { 0x001E6C, 0, { 0x001E6D }},                      /* 1E6C; 1E6D; Case map */
+  { 0x001E6E, 0, { 0x001E6F }},                      /* 1E6E; 1E6F; Case map */
+  { 0x001E70, 0, { 0x001E71 }},                      /* 1E70; 1E71; Case map */
+  { 0x001E72, 0, { 0x001E73 }},                      /* 1E72; 1E73; Case map */
+  { 0x001E74, 0, { 0x001E75 }},                      /* 1E74; 1E75; Case map */
+  { 0x001E76, 0, { 0x001E77 }},                      /* 1E76; 1E77; Case map */
+  { 0x001E78, 0, { 0x001E79 }},                      /* 1E78; 1E79; Case map */
+  { 0x001E7A, 0, { 0x001E7B }},                      /* 1E7A; 1E7B; Case map */
+  { 0x001E7C, 0, { 0x001E7D }},                      /* 1E7C; 1E7D; Case map */
+  { 0x001E7E, 0, { 0x001E7F }},                      /* 1E7E; 1E7F; Case map */
+  { 0x001E80, 0, { 0x001E81 }},                      /* 1E80; 1E81; Case map */
+  { 0x001E82, 0, { 0x001E83 }},                      /* 1E82; 1E83; Case map */
+  { 0x001E84, 0, { 0x001E85 }},                      /* 1E84; 1E85; Case map */
+  { 0x001E86, 0, { 0x001E87 }},                      /* 1E86; 1E87; Case map */
+  { 0x001E88, 0, { 0x001E89 }},                      /* 1E88; 1E89; Case map */
+  { 0x001E8A, 0, { 0x001E8B }},                      /* 1E8A; 1E8B; Case map */
+  { 0x001E8C, 0, { 0x001E8D }},                      /* 1E8C; 1E8D; Case map */
+  { 0x001E8E, 0, { 0x001E8F }},                      /* 1E8E; 1E8F; Case map */
+  { 0x001E90, 0, { 0x001E91 }},                      /* 1E90; 1E91; Case map */
+  { 0x001E92, 0, { 0x001E93 }},                      /* 1E92; 1E93; Case map */
+  { 0x001E94, 0, { 0x001E95 }},                      /* 1E94; 1E95; Case map */
+  { 0x001E96, 0, { 0x000068,                    /* 1E96; 0068 0331; Case map */
+                   0x000331 }},
+  { 0x001E97, 0, { 0x000074,                    /* 1E97; 0074 0308; Case map */
+                   0x000308 }},
+  { 0x001E98, 0, { 0x000077,                    /* 1E98; 0077 030A; Case map */
+                   0x00030A }},
+  { 0x001E99, 0, { 0x000079,                    /* 1E99; 0079 030A; Case map */
+                   0x00030A }},
+  { 0x001E9A, 0, { 0x000061,                    /* 1E9A; 0061 02BE; Case map */
+                   0x0002BE }},
+  { 0x001E9B, 0, { 0x001E61 }},                      /* 1E9B; 1E61; Case map */
+  { 0x001EA0, 0, { 0x001EA1 }},                      /* 1EA0; 1EA1; Case map */
+  { 0x001EA2, 0, { 0x001EA3 }},                      /* 1EA2; 1EA3; Case map */
+  { 0x001EA4, 0, { 0x001EA5 }},                      /* 1EA4; 1EA5; Case map */
+  { 0x001EA6, 0, { 0x001EA7 }},                      /* 1EA6; 1EA7; Case map */
+  { 0x001EA8, 0, { 0x001EA9 }},                      /* 1EA8; 1EA9; Case map */
+  { 0x001EAA, 0, { 0x001EAB }},                      /* 1EAA; 1EAB; Case map */
+  { 0x001EAC, 0, { 0x001EAD }},                      /* 1EAC; 1EAD; Case map */
+  { 0x001EAE, 0, { 0x001EAF }},                      /* 1EAE; 1EAF; Case map */
+  { 0x001EB0, 0, { 0x001EB1 }},                      /* 1EB0; 1EB1; Case map */
+  { 0x001EB2, 0, { 0x001EB3 }},                      /* 1EB2; 1EB3; Case map */
+  { 0x001EB4, 0, { 0x001EB5 }},                      /* 1EB4; 1EB5; Case map */
+  { 0x001EB6, 0, { 0x001EB7 }},                      /* 1EB6; 1EB7; Case map */
+  { 0x001EB8, 0, { 0x001EB9 }},                      /* 1EB8; 1EB9; Case map */
+  { 0x001EBA, 0, { 0x001EBB }},                      /* 1EBA; 1EBB; Case map */
+  { 0x001EBC, 0, { 0x001EBD }},                      /* 1EBC; 1EBD; Case map */
+  { 0x001EBE, 0, { 0x001EBF }},                      /* 1EBE; 1EBF; Case map */
+  { 0x001EC0, 0, { 0x001EC1 }},                      /* 1EC0; 1EC1; Case map */
+  { 0x001EC2, 0, { 0x001EC3 }},                      /* 1EC2; 1EC3; Case map */
+  { 0x001EC4, 0, { 0x001EC5 }},                      /* 1EC4; 1EC5; Case map */
+  { 0x001EC6, 0, { 0x001EC7 }},                      /* 1EC6; 1EC7; Case map */
+  { 0x001EC8, 0, { 0x001EC9 }},                      /* 1EC8; 1EC9; Case map */
+  { 0x001ECA, 0, { 0x001ECB }},                      /* 1ECA; 1ECB; Case map */
+  { 0x001ECC, 0, { 0x001ECD }},                      /* 1ECC; 1ECD; Case map */
+  { 0x001ECE, 0, { 0x001ECF }},                      /* 1ECE; 1ECF; Case map */
+  { 0x001ED0, 0, { 0x001ED1 }},                      /* 1ED0; 1ED1; Case map */
+  { 0x001ED2, 0, { 0x001ED3 }},                      /* 1ED2; 1ED3; Case map */
+  { 0x001ED4, 0, { 0x001ED5 }},                      /* 1ED4; 1ED5; Case map */
+  { 0x001ED6, 0, { 0x001ED7 }},                      /* 1ED6; 1ED7; Case map */
+  { 0x001ED8, 0, { 0x001ED9 }},                      /* 1ED8; 1ED9; Case map */
+  { 0x001EDA, 0, { 0x001EDB }},                      /* 1EDA; 1EDB; Case map */
+  { 0x001EDC, 0, { 0x001EDD }},                      /* 1EDC; 1EDD; Case map */
+  { 0x001EDE, 0, { 0x001EDF }},                      /* 1EDE; 1EDF; Case map */
+  { 0x001EE0, 0, { 0x001EE1 }},                      /* 1EE0; 1EE1; Case map */
+  { 0x001EE2, 0, { 0x001EE3 }},                      /* 1EE2; 1EE3; Case map */
+  { 0x001EE4, 0, { 0x001EE5 }},                      /* 1EE4; 1EE5; Case map */
+  { 0x001EE6, 0, { 0x001EE7 }},                      /* 1EE6; 1EE7; Case map */
+  { 0x001EE8, 0, { 0x001EE9 }},                      /* 1EE8; 1EE9; Case map */
+  { 0x001EEA, 0, { 0x001EEB }},                      /* 1EEA; 1EEB; Case map */
+  { 0x001EEC, 0, { 0x001EED }},                      /* 1EEC; 1EED; Case map */
+  { 0x001EEE, 0, { 0x001EEF }},                      /* 1EEE; 1EEF; Case map */
+  { 0x001EF0, 0, { 0x001EF1 }},                      /* 1EF0; 1EF1; Case map */
+  { 0x001EF2, 0, { 0x001EF3 }},                      /* 1EF2; 1EF3; Case map */
+  { 0x001EF4, 0, { 0x001EF5 }},                      /* 1EF4; 1EF5; Case map */
+  { 0x001EF6, 0, { 0x001EF7 }},                      /* 1EF6; 1EF7; Case map */
+  { 0x001EF8, 0, { 0x001EF9 }},                      /* 1EF8; 1EF9; Case map */
+  { 0x001F08, 0, { 0x001F00 }},                      /* 1F08; 1F00; Case map */
+  { 0x001F09, 0, { 0x001F01 }},                      /* 1F09; 1F01; Case map */
+  { 0x001F0A, 0, { 0x001F02 }},                      /* 1F0A; 1F02; Case map */
+  { 0x001F0B, 0, { 0x001F03 }},                      /* 1F0B; 1F03; Case map */
+  { 0x001F0C, 0, { 0x001F04 }},                      /* 1F0C; 1F04; Case map */
+  { 0x001F0D, 0, { 0x001F05 }},                      /* 1F0D; 1F05; Case map */
+  { 0x001F0E, 0, { 0x001F06 }},                      /* 1F0E; 1F06; Case map */
+  { 0x001F0F, 0, { 0x001F07 }},                      /* 1F0F; 1F07; Case map */
+  { 0x001F18, 0, { 0x001F10 }},                      /* 1F18; 1F10; Case map */
+  { 0x001F19, 0, { 0x001F11 }},                      /* 1F19; 1F11; Case map */
+  { 0x001F1A, 0, { 0x001F12 }},                      /* 1F1A; 1F12; Case map */
+  { 0x001F1B, 0, { 0x001F13 }},                      /* 1F1B; 1F13; Case map */
+  { 0x001F1C, 0, { 0x001F14 }},                      /* 1F1C; 1F14; Case map */
+  { 0x001F1D, 0, { 0x001F15 }},                      /* 1F1D; 1F15; Case map */
+  { 0x001F28, 0, { 0x001F20 }},                      /* 1F28; 1F20; Case map */
+  { 0x001F29, 0, { 0x001F21 }},                      /* 1F29; 1F21; Case map */
+  { 0x001F2A, 0, { 0x001F22 }},                      /* 1F2A; 1F22; Case map */
+  { 0x001F2B, 0, { 0x001F23 }},                      /* 1F2B; 1F23; Case map */
+  { 0x001F2C, 0, { 0x001F24 }},                      /* 1F2C; 1F24; Case map */
+  { 0x001F2D, 0, { 0x001F25 }},                      /* 1F2D; 1F25; Case map */
+  { 0x001F2E, 0, { 0x001F26 }},                      /* 1F2E; 1F26; Case map */
+  { 0x001F2F, 0, { 0x001F27 }},                      /* 1F2F; 1F27; Case map */
+  { 0x001F38, 0, { 0x001F30 }},                      /* 1F38; 1F30; Case map */
+  { 0x001F39, 0, { 0x001F31 }},                      /* 1F39; 1F31; Case map */
+  { 0x001F3A, 0, { 0x001F32 }},                      /* 1F3A; 1F32; Case map */
+  { 0x001F3B, 0, { 0x001F33 }},                      /* 1F3B; 1F33; Case map */
+  { 0x001F3C, 0, { 0x001F34 }},                      /* 1F3C; 1F34; Case map */
+  { 0x001F3D, 0, { 0x001F35 }},                      /* 1F3D; 1F35; Case map */
+  { 0x001F3E, 0, { 0x001F36 }},                      /* 1F3E; 1F36; Case map */
+  { 0x001F3F, 0, { 0x001F37 }},                      /* 1F3F; 1F37; Case map */
+  { 0x001F48, 0, { 0x001F40 }},                      /* 1F48; 1F40; Case map */
+  { 0x001F49, 0, { 0x001F41 }},                      /* 1F49; 1F41; Case map */
+  { 0x001F4A, 0, { 0x001F42 }},                      /* 1F4A; 1F42; Case map */
+  { 0x001F4B, 0, { 0x001F43 }},                      /* 1F4B; 1F43; Case map */
+  { 0x001F4C, 0, { 0x001F44 }},                      /* 1F4C; 1F44; Case map */
+  { 0x001F4D, 0, { 0x001F45 }},                      /* 1F4D; 1F45; Case map */
+  { 0x001F50, 0, { 0x0003C5,                    /* 1F50; 03C5 0313; Case map */
+                   0x000313 }},
+  { 0x001F52, 0, { 0x0003C5,               /* 1F52; 03C5 0313 0300; Case map */
+                   0x000313, 0x000300 }},
+  { 0x001F54, 0, { 0x0003C5,               /* 1F54; 03C5 0313 0301; Case map */
+                   0x000313, 0x000301 }},
+  { 0x001F56, 0, { 0x0003C5,               /* 1F56; 03C5 0313 0342; Case map */
+                   0x000313, 0x000342 }},
+  { 0x001F59, 0, { 0x001F51 }},                      /* 1F59; 1F51; Case map */
+  { 0x001F5B, 0, { 0x001F53 }},                      /* 1F5B; 1F53; Case map */
+  { 0x001F5D, 0, { 0x001F55 }},                      /* 1F5D; 1F55; Case map */
+  { 0x001F5F, 0, { 0x001F57 }},                      /* 1F5F; 1F57; Case map */
+  { 0x001F68, 0, { 0x001F60 }},                      /* 1F68; 1F60; Case map */
+  { 0x001F69, 0, { 0x001F61 }},                      /* 1F69; 1F61; Case map */
+  { 0x001F6A, 0, { 0x001F62 }},                      /* 1F6A; 1F62; Case map */
+  { 0x001F6B, 0, { 0x001F63 }},                      /* 1F6B; 1F63; Case map */
+  { 0x001F6C, 0, { 0x001F64 }},                      /* 1F6C; 1F64; Case map */
+  { 0x001F6D, 0, { 0x001F65 }},                      /* 1F6D; 1F65; Case map */
+  { 0x001F6E, 0, { 0x001F66 }},                      /* 1F6E; 1F66; Case map */
+  { 0x001F6F, 0, { 0x001F67 }},                      /* 1F6F; 1F67; Case map */
+  { 0x001F80, 0, { 0x001F00,                    /* 1F80; 1F00 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F81, 0, { 0x001F01,                    /* 1F81; 1F01 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F82, 0, { 0x001F02,                    /* 1F82; 1F02 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F83, 0, { 0x001F03,                    /* 1F83; 1F03 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F84, 0, { 0x001F04,                    /* 1F84; 1F04 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F85, 0, { 0x001F05,                    /* 1F85; 1F05 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F86, 0, { 0x001F06,                    /* 1F86; 1F06 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F87, 0, { 0x001F07,                    /* 1F87; 1F07 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F88, 0, { 0x001F00,                    /* 1F88; 1F00 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F89, 0, { 0x001F01,                    /* 1F89; 1F01 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8A, 0, { 0x001F02,                    /* 1F8A; 1F02 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8B, 0, { 0x001F03,                    /* 1F8B; 1F03 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8C, 0, { 0x001F04,                    /* 1F8C; 1F04 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8D, 0, { 0x001F05,                    /* 1F8D; 1F05 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8E, 0, { 0x001F06,                    /* 1F8E; 1F06 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F8F, 0, { 0x001F07,                    /* 1F8F; 1F07 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F90, 0, { 0x001F20,                    /* 1F90; 1F20 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F91, 0, { 0x001F21,                    /* 1F91; 1F21 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F92, 0, { 0x001F22,                    /* 1F92; 1F22 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F93, 0, { 0x001F23,                    /* 1F93; 1F23 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F94, 0, { 0x001F24,                    /* 1F94; 1F24 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F95, 0, { 0x001F25,                    /* 1F95; 1F25 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F96, 0, { 0x001F26,                    /* 1F96; 1F26 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F97, 0, { 0x001F27,                    /* 1F97; 1F27 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F98, 0, { 0x001F20,                    /* 1F98; 1F20 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F99, 0, { 0x001F21,                    /* 1F99; 1F21 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9A, 0, { 0x001F22,                    /* 1F9A; 1F22 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9B, 0, { 0x001F23,                    /* 1F9B; 1F23 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9C, 0, { 0x001F24,                    /* 1F9C; 1F24 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9D, 0, { 0x001F25,                    /* 1F9D; 1F25 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9E, 0, { 0x001F26,                    /* 1F9E; 1F26 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001F9F, 0, { 0x001F27,                    /* 1F9F; 1F27 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA0, 0, { 0x001F60,                    /* 1FA0; 1F60 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA1, 0, { 0x001F61,                    /* 1FA1; 1F61 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA2, 0, { 0x001F62,                    /* 1FA2; 1F62 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA3, 0, { 0x001F63,                    /* 1FA3; 1F63 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA4, 0, { 0x001F64,                    /* 1FA4; 1F64 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA5, 0, { 0x001F65,                    /* 1FA5; 1F65 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA6, 0, { 0x001F66,                    /* 1FA6; 1F66 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA7, 0, { 0x001F67,                    /* 1FA7; 1F67 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA8, 0, { 0x001F60,                    /* 1FA8; 1F60 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FA9, 0, { 0x001F61,                    /* 1FA9; 1F61 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAA, 0, { 0x001F62,                    /* 1FAA; 1F62 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAB, 0, { 0x001F63,                    /* 1FAB; 1F63 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAC, 0, { 0x001F64,                    /* 1FAC; 1F64 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAD, 0, { 0x001F65,                    /* 1FAD; 1F65 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAE, 0, { 0x001F66,                    /* 1FAE; 1F66 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FAF, 0, { 0x001F67,                    /* 1FAF; 1F67 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB2, 0, { 0x001F70,                    /* 1FB2; 1F70 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB3, 0, { 0x0003B1,                    /* 1FB3; 03B1 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB4, 0, { 0x0003AC,                    /* 1FB4; 03AC 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FB6, 0, { 0x0003B1,                    /* 1FB6; 03B1 0342; Case map */
+                   0x000342 }},
+  { 0x001FB7, 0, { 0x0003B1,               /* 1FB7; 03B1 0342 03B9; Case map */
+                   0x000342, 0x0003B9 }},
+  { 0x001FB8, 0, { 0x001FB0 }},                      /* 1FB8; 1FB0; Case map */
+  { 0x001FB9, 0, { 0x001FB1 }},                      /* 1FB9; 1FB1; Case map */
+  { 0x001FBA, 0, { 0x001F70 }},                      /* 1FBA; 1F70; Case map */
+  { 0x001FBB, 0, { 0x001F71 }},                      /* 1FBB; 1F71; Case map */
+  { 0x001FBC, 0, { 0x0003B1,                    /* 1FBC; 03B1 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FBE, 0, { 0x0003B9 }},                      /* 1FBE; 03B9; Case map */
+  { 0x001FC2, 0, { 0x001F74,                    /* 1FC2; 1F74 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FC3, 0, { 0x0003B7,                    /* 1FC3; 03B7 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FC4, 0, { 0x0003AE,                    /* 1FC4; 03AE 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FC6, 0, { 0x0003B7,                    /* 1FC6; 03B7 0342; Case map */
+                   0x000342 }},
+  { 0x001FC7, 0, { 0x0003B7,               /* 1FC7; 03B7 0342 03B9; Case map */
+                   0x000342, 0x0003B9 }},
+  { 0x001FC8, 0, { 0x001F72 }},                      /* 1FC8; 1F72; Case map */
+  { 0x001FC9, 0, { 0x001F73 }},                      /* 1FC9; 1F73; Case map */
+  { 0x001FCA, 0, { 0x001F74 }},                      /* 1FCA; 1F74; Case map */
+  { 0x001FCB, 0, { 0x001F75 }},                      /* 1FCB; 1F75; Case map */
+  { 0x001FCC, 0, { 0x0003B7,                    /* 1FCC; 03B7 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FD2, 0, { 0x0003B9,               /* 1FD2; 03B9 0308 0300; Case map */
+                   0x000308, 0x000300 }},
+  { 0x001FD3, 0, { 0x0003B9,               /* 1FD3; 03B9 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x001FD6, 0, { 0x0003B9,                    /* 1FD6; 03B9 0342; Case map */
+                   0x000342 }},
+  { 0x001FD7, 0, { 0x0003B9,               /* 1FD7; 03B9 0308 0342; Case map */
+                   0x000308, 0x000342 }},
+  { 0x001FD8, 0, { 0x001FD0 }},                      /* 1FD8; 1FD0; Case map */
+  { 0x001FD9, 0, { 0x001FD1 }},                      /* 1FD9; 1FD1; Case map */
+  { 0x001FDA, 0, { 0x001F76 }},                      /* 1FDA; 1F76; Case map */
+  { 0x001FDB, 0, { 0x001F77 }},                      /* 1FDB; 1F77; Case map */
+  { 0x001FE2, 0, { 0x0003C5,               /* 1FE2; 03C5 0308 0300; Case map */
+                   0x000308, 0x000300 }},
+  { 0x001FE3, 0, { 0x0003C5,               /* 1FE3; 03C5 0308 0301; Case map */
+                   0x000308, 0x000301 }},
+  { 0x001FE4, 0, { 0x0003C1,                    /* 1FE4; 03C1 0313; Case map */
+                   0x000313 }},
+  { 0x001FE6, 0, { 0x0003C5,                    /* 1FE6; 03C5 0342; Case map */
+                   0x000342 }},
+  { 0x001FE7, 0, { 0x0003C5,               /* 1FE7; 03C5 0308 0342; Case map */
+                   0x000308, 0x000342 }},
+  { 0x001FE8, 0, { 0x001FE0 }},                      /* 1FE8; 1FE0; Case map */
+  { 0x001FE9, 0, { 0x001FE1 }},                      /* 1FE9; 1FE1; Case map */
+  { 0x001FEA, 0, { 0x001F7A }},                      /* 1FEA; 1F7A; Case map */
+  { 0x001FEB, 0, { 0x001F7B }},                      /* 1FEB; 1F7B; Case map */
+  { 0x001FEC, 0, { 0x001FE5 }},                      /* 1FEC; 1FE5; Case map */
+  { 0x001FF2, 0, { 0x001F7C,                    /* 1FF2; 1F7C 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FF3, 0, { 0x0003C9,                    /* 1FF3; 03C9 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FF4, 0, { 0x0003CE,                    /* 1FF4; 03CE 03B9; Case map */
+                   0x0003B9 }},
+  { 0x001FF6, 0, { 0x0003C9,                    /* 1FF6; 03C9 0342; Case map */
+                   0x000342 }},
+  { 0x001FF7, 0, { 0x0003C9,               /* 1FF7; 03C9 0342 03B9; Case map */
+                   0x000342, 0x0003B9 }},
+  { 0x001FF8, 0, { 0x001F78 }},                      /* 1FF8; 1F78; Case map */
+  { 0x001FF9, 0, { 0x001F79 }},                      /* 1FF9; 1F79; Case map */
+  { 0x001FFA, 0, { 0x001F7C }},                      /* 1FFA; 1F7C; Case map */
+  { 0x001FFB, 0, { 0x001F7D }},                      /* 1FFB; 1F7D; Case map */
+  { 0x001FFC, 0, { 0x0003C9,                    /* 1FFC; 03C9 03B9; Case map */
+                   0x0003B9 }},
+  { 0x002126, 0, { 0x0003C9 }},                      /* 2126; 03C9; Case map */
+  { 0x00212A, 0, { 0x00006B }},                      /* 212A; 006B; Case map */
+  { 0x00212B, 0, { 0x0000E5 }},                      /* 212B; 00E5; Case map */
+  { 0x002160, 0, { 0x002170 }},                      /* 2160; 2170; Case map */
+  { 0x002161, 0, { 0x002171 }},                      /* 2161; 2171; Case map */
+  { 0x002162, 0, { 0x002172 }},                      /* 2162; 2172; Case map */
+  { 0x002163, 0, { 0x002173 }},                      /* 2163; 2173; Case map */
+  { 0x002164, 0, { 0x002174 }},                      /* 2164; 2174; Case map */
+  { 0x002165, 0, { 0x002175 }},                      /* 2165; 2175; Case map */
+  { 0x002166, 0, { 0x002176 }},                      /* 2166; 2176; Case map */
+  { 0x002167, 0, { 0x002177 }},                      /* 2167; 2177; Case map */
+  { 0x002168, 0, { 0x002178 }},                      /* 2168; 2178; Case map */
+  { 0x002169, 0, { 0x002179 }},                      /* 2169; 2179; Case map */
+  { 0x00216A, 0, { 0x00217A }},                      /* 216A; 217A; Case map */
+  { 0x00216B, 0, { 0x00217B }},                      /* 216B; 217B; Case map */
+  { 0x00216C, 0, { 0x00217C }},                      /* 216C; 217C; Case map */
+  { 0x00216D, 0, { 0x00217D }},                      /* 216D; 217D; Case map */
+  { 0x00216E, 0, { 0x00217E }},                      /* 216E; 217E; Case map */
+  { 0x00216F, 0, { 0x00217F }},                      /* 216F; 217F; Case map */
+  { 0x0024B6, 0, { 0x0024D0 }},                      /* 24B6; 24D0; Case map */
+  { 0x0024B7, 0, { 0x0024D1 }},                      /* 24B7; 24D1; Case map */
+  { 0x0024B8, 0, { 0x0024D2 }},                      /* 24B8; 24D2; Case map */
+  { 0x0024B9, 0, { 0x0024D3 }},                      /* 24B9; 24D3; Case map */
+  { 0x0024BA, 0, { 0x0024D4 }},                      /* 24BA; 24D4; Case map */
+  { 0x0024BB, 0, { 0x0024D5 }},                      /* 24BB; 24D5; Case map */
+  { 0x0024BC, 0, { 0x0024D6 }},                      /* 24BC; 24D6; Case map */
+  { 0x0024BD, 0, { 0x0024D7 }},                      /* 24BD; 24D7; Case map */
+  { 0x0024BE, 0, { 0x0024D8 }},                      /* 24BE; 24D8; Case map */
+  { 0x0024BF, 0, { 0x0024D9 }},                      /* 24BF; 24D9; Case map */
+  { 0x0024C0, 0, { 0x0024DA }},                      /* 24C0; 24DA; Case map */
+  { 0x0024C1, 0, { 0x0024DB }},                      /* 24C1; 24DB; Case map */
+  { 0x0024C2, 0, { 0x0024DC }},                      /* 24C2; 24DC; Case map */
+  { 0x0024C3, 0, { 0x0024DD }},                      /* 24C3; 24DD; Case map */
+  { 0x0024C4, 0, { 0x0024DE }},                      /* 24C4; 24DE; Case map */
+  { 0x0024C5, 0, { 0x0024DF }},                      /* 24C5; 24DF; Case map */
+  { 0x0024C6, 0, { 0x0024E0 }},                      /* 24C6; 24E0; Case map */
+  { 0x0024C7, 0, { 0x0024E1 }},                      /* 24C7; 24E1; Case map */
+  { 0x0024C8, 0, { 0x0024E2 }},                      /* 24C8; 24E2; Case map */
+  { 0x0024C9, 0, { 0x0024E3 }},                      /* 24C9; 24E3; Case map */
+  { 0x0024CA, 0, { 0x0024E4 }},                      /* 24CA; 24E4; Case map */
+  { 0x0024CB, 0, { 0x0024E5 }},                      /* 24CB; 24E5; Case map */
+  { 0x0024CC, 0, { 0x0024E6 }},                      /* 24CC; 24E6; Case map */
+  { 0x0024CD, 0, { 0x0024E7 }},                      /* 24CD; 24E7; Case map */
+  { 0x0024CE, 0, { 0x0024E8 }},                      /* 24CE; 24E8; Case map */
+  { 0x0024CF, 0, { 0x0024E9 }},                      /* 24CF; 24E9; Case map */
+  { 0x00FB00, 0, { 0x000066,                    /* FB00; 0066 0066; Case map */
+                   0x000066 }},
+  { 0x00FB01, 0, { 0x000066,                    /* FB01; 0066 0069; Case map */
+                   0x000069 }},
+  { 0x00FB02, 0, { 0x000066,                    /* FB02; 0066 006C; Case map */
+                   0x00006C }},
+  { 0x00FB03, 0, { 0x000066,               /* FB03; 0066 0066 0069; Case map */
+                   0x000066, 0x000069 }},
+  { 0x00FB04, 0, { 0x000066,               /* FB04; 0066 0066 006C; Case map */
+                   0x000066, 0x00006C }},
+  { 0x00FB05, 0, { 0x000073,                    /* FB05; 0073 0074; Case map */
+                   0x000074 }},
+  { 0x00FB06, 0, { 0x000073,                    /* FB06; 0073 0074; Case map */
+                   0x000074 }},
+  { 0x00FB13, 0, { 0x000574,                    /* FB13; 0574 0576; Case map */
+                   0x000576 }},
+  { 0x00FB14, 0, { 0x000574,                    /* FB14; 0574 0565; Case map */
+                   0x000565 }},
+  { 0x00FB15, 0, { 0x000574,                    /* FB15; 0574 056B; Case map */
+                   0x00056B }},
+  { 0x00FB16, 0, { 0x00057E,                    /* FB16; 057E 0576; Case map */
+                   0x000576 }},
+  { 0x00FB17, 0, { 0x000574,                    /* FB17; 0574 056D; Case map */
+                   0x00056D }},
+  { 0x00FF21, 0, { 0x00FF41 }},                      /* FF21; FF41; Case map */
+  { 0x00FF22, 0, { 0x00FF42 }},                      /* FF22; FF42; Case map */
+  { 0x00FF23, 0, { 0x00FF43 }},                      /* FF23; FF43; Case map */
+  { 0x00FF24, 0, { 0x00FF44 }},                      /* FF24; FF44; Case map */
+  { 0x00FF25, 0, { 0x00FF45 }},                      /* FF25; FF45; Case map */
+  { 0x00FF26, 0, { 0x00FF46 }},                      /* FF26; FF46; Case map */
+  { 0x00FF27, 0, { 0x00FF47 }},                      /* FF27; FF47; Case map */
+  { 0x00FF28, 0, { 0x00FF48 }},                      /* FF28; FF48; Case map */
+  { 0x00FF29, 0, { 0x00FF49 }},                      /* FF29; FF49; Case map */
+  { 0x00FF2A, 0, { 0x00FF4A }},                      /* FF2A; FF4A; Case map */
+  { 0x00FF2B, 0, { 0x00FF4B }},                      /* FF2B; FF4B; Case map */
+  { 0x00FF2C, 0, { 0x00FF4C }},                      /* FF2C; FF4C; Case map */
+  { 0x00FF2D, 0, { 0x00FF4D }},                      /* FF2D; FF4D; Case map */
+  { 0x00FF2E, 0, { 0x00FF4E }},                      /* FF2E; FF4E; Case map */
+  { 0x00FF2F, 0, { 0x00FF4F }},                      /* FF2F; FF4F; Case map */
+  { 0x00FF30, 0, { 0x00FF50 }},                      /* FF30; FF50; Case map */
+  { 0x00FF31, 0, { 0x00FF51 }},                      /* FF31; FF51; Case map */
+  { 0x00FF32, 0, { 0x00FF52 }},                      /* FF32; FF52; Case map */
+  { 0x00FF33, 0, { 0x00FF53 }},                      /* FF33; FF53; Case map */
+  { 0x00FF34, 0, { 0x00FF54 }},                      /* FF34; FF54; Case map */
+  { 0x00FF35, 0, { 0x00FF55 }},                      /* FF35; FF55; Case map */
+  { 0x00FF36, 0, { 0x00FF56 }},                      /* FF36; FF56; Case map */
+  { 0x00FF37, 0, { 0x00FF57 }},                      /* FF37; FF57; Case map */
+  { 0x00FF38, 0, { 0x00FF58 }},                      /* FF38; FF58; Case map */
+  { 0x00FF39, 0, { 0x00FF59 }},                      /* FF39; FF59; Case map */
+  { 0x00FF3A, 0, { 0x00FF5A }},                      /* FF3A; FF5A; Case map */
+  { 0x010400, 0, { 0x010428 }},                    /* 10400; 10428; Case map */
+  { 0x010401, 0, { 0x010429 }},                    /* 10401; 10429; Case map */
+  { 0x010402, 0, { 0x01042A }},                    /* 10402; 1042A; Case map */
+  { 0x010403, 0, { 0x01042B }},                    /* 10403; 1042B; Case map */
+  { 0x010404, 0, { 0x01042C }},                    /* 10404; 1042C; Case map */
+  { 0x010405, 0, { 0x01042D }},                    /* 10405; 1042D; Case map */
+  { 0x010406, 0, { 0x01042E }},                    /* 10406; 1042E; Case map */
+  { 0x010407, 0, { 0x01042F }},                    /* 10407; 1042F; Case map */
+  { 0x010408, 0, { 0x010430 }},                    /* 10408; 10430; Case map */
+  { 0x010409, 0, { 0x010431 }},                    /* 10409; 10431; Case map */
+  { 0x01040A, 0, { 0x010432 }},                    /* 1040A; 10432; Case map */
+  { 0x01040B, 0, { 0x010433 }},                    /* 1040B; 10433; Case map */
+  { 0x01040C, 0, { 0x010434 }},                    /* 1040C; 10434; Case map */
+  { 0x01040D, 0, { 0x010435 }},                    /* 1040D; 10435; Case map */
+  { 0x01040E, 0, { 0x010436 }},                    /* 1040E; 10436; Case map */
+  { 0x01040F, 0, { 0x010437 }},                    /* 1040F; 10437; Case map */
+  { 0x010410, 0, { 0x010438 }},                    /* 10410; 10438; Case map */
+  { 0x010411, 0, { 0x010439 }},                    /* 10411; 10439; Case map */
+  { 0x010412, 0, { 0x01043A }},                    /* 10412; 1043A; Case map */
+  { 0x010413, 0, { 0x01043B }},                    /* 10413; 1043B; Case map */
+  { 0x010414, 0, { 0x01043C }},                    /* 10414; 1043C; Case map */
+  { 0x010415, 0, { 0x01043D }},                    /* 10415; 1043D; Case map */
+  { 0x010416, 0, { 0x01043E }},                    /* 10416; 1043E; Case map */
+  { 0x010417, 0, { 0x01043F }},                    /* 10417; 1043F; Case map */
+  { 0x010418, 0, { 0x010440 }},                    /* 10418; 10440; Case map */
+  { 0x010419, 0, { 0x010441 }},                    /* 10419; 10441; Case map */
+  { 0x01041A, 0, { 0x010442 }},                    /* 1041A; 10442; Case map */
+  { 0x01041B, 0, { 0x010443 }},                    /* 1041B; 10443; Case map */
+  { 0x01041C, 0, { 0x010444 }},                    /* 1041C; 10444; Case map */
+  { 0x01041D, 0, { 0x010445 }},                    /* 1041D; 10445; Case map */
+  { 0x01041E, 0, { 0x010446 }},                    /* 1041E; 10446; Case map */
+  { 0x01041F, 0, { 0x010447 }},                    /* 1041F; 10447; Case map */
+  { 0x010420, 0, { 0x010448 }},                    /* 10420; 10448; Case map */
+  { 0x010421, 0, { 0x010449 }},                    /* 10421; 10449; Case map */
+  { 0x010422, 0, { 0x01044A }},                    /* 10422; 1044A; Case map */
+  { 0x010423, 0, { 0x01044B }},                    /* 10423; 1044B; Case map */
+  { 0x010424, 0, { 0x01044C }},                    /* 10424; 1044C; Case map */
+  { 0x010425, 0, { 0x01044D }},                    /* 10425; 1044D; Case map */
+  { 0 },
+};
+
+
+/*
+ * C.1.1 ASCII space characters
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_1_1[] = {
+  { 0x000020           },                                     /* 0020; SPACE */
+  { 0 },
+};
+
+
+/*
+ * C.1.2 Non-ASCII space characters
+ *  */
+
+const Stringprep_table_element stringprep_rfc3454_C_1_2[] = {
+  { 0x0000A0           },                            /* 00A0; NO-BREAK SPACE */
+  { 0x001680           },                          /* 1680; OGHAM SPACE MARK */
+  { 0x002000           },                                   /* 2000; EN QUAD */
+  { 0x002001           },                                   /* 2001; EM QUAD */
+  { 0x002002           },                                  /* 2002; EN SPACE */
+  { 0x002003           },                                  /* 2003; EM SPACE */
+  { 0x002004           },                        /* 2004; THREE-PER-EM SPACE */
+  { 0x002005           },                         /* 2005; FOUR-PER-EM SPACE */
+  { 0x002006           },                          /* 2006; SIX-PER-EM SPACE */
+  { 0x002007           },                              /* 2007; FIGURE SPACE */
+  { 0x002008           },                         /* 2008; PUNCTUATION SPACE */
+  { 0x002009           },                                /* 2009; THIN SPACE */
+  { 0x00200A           },                                /* 200A; HAIR SPACE */
+  { 0x00200B           },                          /* 200B; ZERO WIDTH SPACE */
+  { 0x00202F           },                     /* 202F; NARROW NO-BREAK SPACE */
+  { 0x00205F           },                 /* 205F; MEDIUM MATHEMATICAL SPACE */
+  { 0x003000           },                         /* 3000; IDEOGRAPHIC SPACE */
+  { 0 },
+};
+
+
+/*
+ * C.2.1 ASCII control characters
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_2_1[] = {
+  { 0x000000, 0x00001F },                 /* 0000-001F; [CONTROL CHARACTERS] */
+  { 0x00007F           },                                    /* 007F; DELETE */
+  { 0 },
+};
+
+
+/*
+ * C.2.2 Non-ASCII control characters
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_2_2[] = {
+  { 0x000080, 0x00009F },                 /* 0080-009F; [CONTROL CHARACTERS] */
+  { 0x0006DD           },                        /* 06DD; ARABIC END OF AYAH */
+  { 0x00070F           },                  /* 070F; SYRIAC ABBREVIATION MARK */
+  { 0x00180E           },                 /* 180E; MONGOLIAN VOWEL SEPARATOR */
+  { 0x00200C           },                     /* 200C; ZERO WIDTH NON-JOINER */
+  { 0x00200D           },                         /* 200D; ZERO WIDTH JOINER */
+  { 0x002028           },                            /* 2028; LINE SEPARATOR */
+  { 0x002029           },                       /* 2029; PARAGRAPH SEPARATOR */
+  { 0x002060           },                               /* 2060; WORD JOINER */
+  { 0x002061           },                      /* 2061; FUNCTION APPLICATION */
+  { 0x002062           },                           /* 2062; INVISIBLE TIMES */
+  { 0x002063           },                       /* 2063; INVISIBLE SEPARATOR */
+  { 0x00206A, 0x00206F },                 /* 206A-206F; [CONTROL CHARACTERS] */
+  { 0x00FEFF           },                 /* FEFF; ZERO WIDTH NO-BREAK SPACE */
+  { 0x00FFF9, 0x00FFFC },                 /* FFF9-FFFC; [CONTROL CHARACTERS] */
+  { 0x01D173, 0x01D17A },       /* 1D173-1D17A; [MUSICAL CONTROL CHARACTERS] */
+  { 0 },
+};
+
+
+/*
+ * C.3 Private use
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_3[] = {
+  { 0x00E000, 0x00F8FF },               /* E000-F8FF; [PRIVATE USE, PLANE 0] */
+  { 0x0F0000, 0x0FFFFD },            /* F0000-FFFFD; [PRIVATE USE, PLANE 15] */
+  { 0x100000, 0x10FFFD },          /* 100000-10FFFD; [PRIVATE USE, PLANE 16] */
+  { 0 },
+};
+
+
+/*
+ * C.4 Non-character code points
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_4[] = {
+  { 0x00FDD0, 0x00FDEF },           /* FDD0-FDEF; [NONCHARACTER CODE POINTS] */
+  { 0x00FFFE, 0x00FFFF },           /* FFFE-FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x01FFFE, 0x01FFFF },         /* 1FFFE-1FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x02FFFE, 0x02FFFF },         /* 2FFFE-2FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x03FFFE, 0x03FFFF },         /* 3FFFE-3FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x04FFFE, 0x04FFFF },         /* 4FFFE-4FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x05FFFE, 0x05FFFF },         /* 5FFFE-5FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x06FFFE, 0x06FFFF },         /* 6FFFE-6FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x07FFFE, 0x07FFFF },         /* 7FFFE-7FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x08FFFE, 0x08FFFF },         /* 8FFFE-8FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x09FFFE, 0x09FFFF },         /* 9FFFE-9FFFF; [NONCHARACTER CODE POINTS] */
+  { 0x0AFFFE, 0x0AFFFF },         /* AFFFE-AFFFF; [NONCHARACTER CODE POINTS] */
+  { 0x0BFFFE, 0x0BFFFF },         /* BFFFE-BFFFF; [NONCHARACTER CODE POINTS] */
+  { 0x0CFFFE, 0x0CFFFF },         /* CFFFE-CFFFF; [NONCHARACTER CODE POINTS] */
+  { 0x0DFFFE, 0x0DFFFF },         /* DFFFE-DFFFF; [NONCHARACTER CODE POINTS] */
+  { 0x0EFFFE, 0x0EFFFF },         /* EFFFE-EFFFF; [NONCHARACTER CODE POINTS] */
+  { 0x0FFFFE, 0x0FFFFF },         /* FFFFE-FFFFF; [NONCHARACTER CODE POINTS] */
+  { 0x10FFFE, 0x10FFFF },       /* 10FFFE-10FFFF; [NONCHARACTER CODE POINTS] */
+  { 0 },
+};
+
+
+/*
+ * C.5 Surrogate codes
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_5[] = {
+  { 0x00D800, 0x00DFFF },                    /* D800-DFFF; [SURROGATE CODES] */
+  { 0 },
+};
+
+
+/*
+ * C.6 Inappropriate for plain text
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_6[] = {
+  { 0x00FFF9           },             /* FFF9; INTERLINEAR ANNOTATION ANCHOR */
+  { 0x00FFFA           },          /* FFFA; INTERLINEAR ANNOTATION SEPARATOR */
+  { 0x00FFFB           },         /* FFFB; INTERLINEAR ANNOTATION TERMINATOR */
+  { 0x00FFFC           },              /* FFFC; OBJECT REPLACEMENT CHARACTER */
+  { 0x00FFFD           },                     /* FFFD; REPLACEMENT CHARACTER */
+  { 0 },
+};
+
+
+/*
+ * C.7 Inappropriate for canonical representation
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_7[] = {
+  { 0x002FF0, 0x002FFB }, /* 2FF0-2FFB; [IDEOGRAPHIC DESCRIPTION CHARACTERS] */
+  { 0 },
+};
+
+
+/*
+ * C.8 Change display properties or are deprecated
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_8[] = {
+  { 0x000340           },                 /* 0340; COMBINING GRAVE TONE MARK */
+  { 0x000341           },                 /* 0341; COMBINING ACUTE TONE MARK */
+  { 0x00200E           },                        /* 200E; LEFT-TO-RIGHT MARK */
+  { 0x00200F           },                        /* 200F; RIGHT-TO-LEFT MARK */
+  { 0x00202A           },                   /* 202A; LEFT-TO-RIGHT EMBEDDING */
+  { 0x00202B           },                   /* 202B; RIGHT-TO-LEFT EMBEDDING */
+  { 0x00202C           },                /* 202C; POP DIRECTIONAL FORMATTING */
+  { 0x00202D           },                    /* 202D; LEFT-TO-RIGHT OVERRIDE */
+  { 0x00202E           },                    /* 202E; RIGHT-TO-LEFT OVERRIDE */
+  { 0x00206A           },                /* 206A; INHIBIT SYMMETRIC SWAPPING */
+  { 0x00206B           },               /* 206B; ACTIVATE SYMMETRIC SWAPPING */
+  { 0x00206C           },               /* 206C; INHIBIT ARABIC FORM SHAPING */
+  { 0x00206D           },              /* 206D; ACTIVATE ARABIC FORM SHAPING */
+  { 0x00206E           },                     /* 206E; NATIONAL DIGIT SHAPES */
+  { 0x00206F           },                      /* 206F; NOMINAL DIGIT SHAPES */
+  { 0 },
+};
+
+
+/*
+ * C.9 Tagging characters
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_C_9[] = {
+  { 0x0E0001           },                             /* E0001; LANGUAGE TAG */
+  { 0x0E0020, 0x0E007F },               /* E0020-E007F; [TAGGING CHARACTERS] */
+  { 0 },
+};
+
+
+/*
+ * D.1 Characters with bidirectional property "R" or "AL"
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_D_1[] = {
+  { 0x0005BE           },                                            /* 05BE */
+  { 0x0005C0           },                                            /* 05C0 */
+  { 0x0005C3           },                                            /* 05C3 */
+  { 0x0005D0, 0x0005EA },                                       /* 05D0-05EA */
+  { 0x0005F0, 0x0005F4 },                                       /* 05F0-05F4 */
+  { 0x00061B           },                                            /* 061B */
+  { 0x00061F           },                                            /* 061F */
+  { 0x000621, 0x00063A },                                       /* 0621-063A */
+  { 0x000640, 0x00064A },                                       /* 0640-064A */
+  { 0x00066D, 0x00066F },                                       /* 066D-066F */
+  { 0x000671, 0x0006D5 },                                       /* 0671-06D5 */
+  { 0x0006DD           },                                            /* 06DD */
+  { 0x0006E5, 0x0006E6 },                                       /* 06E5-06E6 */
+  { 0x0006FA, 0x0006FE },                                       /* 06FA-06FE */
+  { 0x000700, 0x00070D },                                       /* 0700-070D */
+  { 0x000710           },                                            /* 0710 */
+  { 0x000712, 0x00072C },                                       /* 0712-072C */
+  { 0x000780, 0x0007A5 },                                       /* 0780-07A5 */
+  { 0x0007B1           },                                            /* 07B1 */
+  { 0x00200F           },                                            /* 200F */
+  { 0x00FB1D           },                                            /* FB1D */
+  { 0x00FB1F, 0x00FB28 },                                       /* FB1F-FB28 */
+  { 0x00FB2A, 0x00FB36 },                                       /* FB2A-FB36 */
+  { 0x00FB38, 0x00FB3C },                                       /* FB38-FB3C */
+  { 0x00FB3E           },                                            /* FB3E */
+  { 0x00FB40, 0x00FB41 },                                       /* FB40-FB41 */
+  { 0x00FB43, 0x00FB44 },                                       /* FB43-FB44 */
+  { 0x00FB46, 0x00FBB1 },                                       /* FB46-FBB1 */
+  { 0x00FBD3, 0x00FD3D },                                       /* FBD3-FD3D */
+  { 0x00FD50, 0x00FD8F },                                       /* FD50-FD8F */
+  { 0x00FD92, 0x00FDC7 },                                       /* FD92-FDC7 */
+  { 0x00FDF0, 0x00FDFC },                                       /* FDF0-FDFC */
+  { 0x00FE70, 0x00FE74 },                                       /* FE70-FE74 */
+  { 0x00FE76, 0x00FEFC },                                       /* FE76-FEFC */
+  { 0 },
+};
+
+
+/*
+ * D.2 Characters with bidirectional property "L"
+ * 
+ */
+
+const Stringprep_table_element stringprep_rfc3454_D_2[] = {
+  { 0x000041, 0x00005A },                                       /* 0041-005A */
+  { 0x000061, 0x00007A },                                       /* 0061-007A */
+  { 0x0000AA           },                                            /* 00AA */
+  { 0x0000B5           },                                            /* 00B5 */
+  { 0x0000BA           },                                            /* 00BA */
+  { 0x0000C0, 0x0000D6 },                                       /* 00C0-00D6 */
+  { 0x0000D8, 0x0000F6 },                                       /* 00D8-00F6 */
+  { 0x0000F8, 0x000220 },                                       /* 00F8-0220 */
+  { 0x000222, 0x000233 },                                       /* 0222-0233 */
+  { 0x000250, 0x0002AD },                                       /* 0250-02AD */
+  { 0x0002B0, 0x0002B8 },                                       /* 02B0-02B8 */
+  { 0x0002BB, 0x0002C1 },                                       /* 02BB-02C1 */
+  { 0x0002D0, 0x0002D1 },                                       /* 02D0-02D1 */
+  { 0x0002E0, 0x0002E4 },                                       /* 02E0-02E4 */
+  { 0x0002EE           },                                            /* 02EE */
+  { 0x00037A           },                                            /* 037A */
+  { 0x000386           },                                            /* 0386 */
+  { 0x000388, 0x00038A },                                       /* 0388-038A */
+  { 0x00038C           },                                            /* 038C */
+  { 0x00038E, 0x0003A1 },                                       /* 038E-03A1 */
+  { 0x0003A3, 0x0003CE },                                       /* 03A3-03CE */
+  { 0x0003D0, 0x0003F5 },                                       /* 03D0-03F5 */
+  { 0x000400, 0x000482 },                                       /* 0400-0482 */
+  { 0x00048A, 0x0004CE },                                       /* 048A-04CE */
+  { 0x0004D0, 0x0004F5 },                                       /* 04D0-04F5 */
+  { 0x0004F8, 0x0004F9 },                                       /* 04F8-04F9 */
+  { 0x000500, 0x00050F },                                       /* 0500-050F */
+  { 0x000531, 0x000556 },                                       /* 0531-0556 */
+  { 0x000559, 0x00055F },                                       /* 0559-055F */
+  { 0x000561, 0x000587 },                                       /* 0561-0587 */
+  { 0x000589           },                                            /* 0589 */
+  { 0x000903           },                                            /* 0903 */
+  { 0x000905, 0x000939 },                                       /* 0905-0939 */
+  { 0x00093D, 0x000940 },                                       /* 093D-0940 */
+  { 0x000949, 0x00094C },                                       /* 0949-094C */
+  { 0x000950           },                                            /* 0950 */
+  { 0x000958, 0x000961 },                                       /* 0958-0961 */
+  { 0x000964, 0x000970 },                                       /* 0964-0970 */
+  { 0x000982, 0x000983 },                                       /* 0982-0983 */
+  { 0x000985, 0x00098C },                                       /* 0985-098C */
+  { 0x00098F, 0x000990 },                                       /* 098F-0990 */
+  { 0x000993, 0x0009A8 },                                       /* 0993-09A8 */
+  { 0x0009AA, 0x0009B0 },                                       /* 09AA-09B0 */
+  { 0x0009B2           },                                            /* 09B2 */
+  { 0x0009B6, 0x0009B9 },                                       /* 09B6-09B9 */
+  { 0x0009BE, 0x0009C0 },                                       /* 09BE-09C0 */
+  { 0x0009C7, 0x0009C8 },                                       /* 09C7-09C8 */
+  { 0x0009CB, 0x0009CC },                                       /* 09CB-09CC */
+  { 0x0009D7           },                                            /* 09D7 */
+  { 0x0009DC, 0x0009DD },                                       /* 09DC-09DD */
+  { 0x0009DF, 0x0009E1 },                                       /* 09DF-09E1 */
+  { 0x0009E6, 0x0009F1 },                                       /* 09E6-09F1 */
+  { 0x0009F4, 0x0009FA },                                       /* 09F4-09FA */
+  { 0x000A05, 0x000A0A },                                       /* 0A05-0A0A */
+  { 0x000A0F, 0x000A10 },                                       /* 0A0F-0A10 */
+  { 0x000A13, 0x000A28 },                                       /* 0A13-0A28 */
+  { 0x000A2A, 0x000A30 },                                       /* 0A2A-0A30 */
+  { 0x000A32, 0x000A33 },                                       /* 0A32-0A33 */
+  { 0x000A35, 0x000A36 },                                       /* 0A35-0A36 */
+  { 0x000A38, 0x000A39 },                                       /* 0A38-0A39 */
+  { 0x000A3E, 0x000A40 },                                       /* 0A3E-0A40 */
+  { 0x000A59, 0x000A5C },                                       /* 0A59-0A5C */
+  { 0x000A5E           },                                            /* 0A5E */
+  { 0x000A66, 0x000A6F },                                       /* 0A66-0A6F */
+  { 0x000A72, 0x000A74 },                                       /* 0A72-0A74 */
+  { 0x000A83           },                                            /* 0A83 */
+  { 0x000A85, 0x000A8B },                                       /* 0A85-0A8B */
+  { 0x000A8D           },                                            /* 0A8D */
+  { 0x000A8F, 0x000A91 },                                       /* 0A8F-0A91 */
+  { 0x000A93, 0x000AA8 },                                       /* 0A93-0AA8 */
+  { 0x000AAA, 0x000AB0 },                                       /* 0AAA-0AB0 */
+  { 0x000AB2, 0x000AB3 },                                       /* 0AB2-0AB3 */
+  { 0x000AB5, 0x000AB9 },                                       /* 0AB5-0AB9 */
+  { 0x000ABD, 0x000AC0 },                                       /* 0ABD-0AC0 */
+  { 0x000AC9           },                                            /* 0AC9 */
+  { 0x000ACB, 0x000ACC },                                       /* 0ACB-0ACC */
+  { 0x000AD0           },                                            /* 0AD0 */
+  { 0x000AE0           },                                            /* 0AE0 */
+  { 0x000AE6, 0x000AEF },                                       /* 0AE6-0AEF */
+  { 0x000B02, 0x000B03 },                                       /* 0B02-0B03 */
+  { 0x000B05, 0x000B0C },                                       /* 0B05-0B0C */
+  { 0x000B0F, 0x000B10 },                                       /* 0B0F-0B10 */
+  { 0x000B13, 0x000B28 },                                       /* 0B13-0B28 */
+  { 0x000B2A, 0x000B30 },                                       /* 0B2A-0B30 */
+  { 0x000B32, 0x000B33 },                                       /* 0B32-0B33 */
+  { 0x000B36, 0x000B39 },                                       /* 0B36-0B39 */
+  { 0x000B3D, 0x000B3E },                                       /* 0B3D-0B3E */
+  { 0x000B40           },                                            /* 0B40 */
+  { 0x000B47, 0x000B48 },                                       /* 0B47-0B48 */
+  { 0x000B4B, 0x000B4C },                                       /* 0B4B-0B4C */
+  { 0x000B57           },                                            /* 0B57 */
+  { 0x000B5C, 0x000B5D },                                       /* 0B5C-0B5D */
+  { 0x000B5F, 0x000B61 },                                       /* 0B5F-0B61 */
+  { 0x000B66, 0x000B70 },                                       /* 0B66-0B70 */
+  { 0x000B83           },                                            /* 0B83 */
+  { 0x000B85, 0x000B8A },                                       /* 0B85-0B8A */
+  { 0x000B8E, 0x000B90 },                                       /* 0B8E-0B90 */
+  { 0x000B92, 0x000B95 },                                       /* 0B92-0B95 */
+  { 0x000B99, 0x000B9A },                                       /* 0B99-0B9A */
+  { 0x000B9C           },                                            /* 0B9C */
+  { 0x000B9E, 0x000B9F },                                       /* 0B9E-0B9F */
+  { 0x000BA3, 0x000BA4 },                                       /* 0BA3-0BA4 */
+  { 0x000BA8, 0x000BAA },                                       /* 0BA8-0BAA */
+  { 0x000BAE, 0x000BB5 },                                       /* 0BAE-0BB5 */
+  { 0x000BB7, 0x000BB9 },                                       /* 0BB7-0BB9 */
+  { 0x000BBE, 0x000BBF },                                       /* 0BBE-0BBF */
+  { 0x000BC1, 0x000BC2 },                                       /* 0BC1-0BC2 */
+  { 0x000BC6, 0x000BC8 },                                       /* 0BC6-0BC8 */
+  { 0x000BCA, 0x000BCC },                                       /* 0BCA-0BCC */
+  { 0x000BD7           },                                            /* 0BD7 */
+  { 0x000BE7, 0x000BF2 },                                       /* 0BE7-0BF2 */
+  { 0x000C01, 0x000C03 },                                       /* 0C01-0C03 */
+  { 0x000C05, 0x000C0C },                                       /* 0C05-0C0C */
+  { 0x000C0E, 0x000C10 },                                       /* 0C0E-0C10 */
+  { 0x000C12, 0x000C28 },                                       /* 0C12-0C28 */
+  { 0x000C2A, 0x000C33 },                                       /* 0C2A-0C33 */
+  { 0x000C35, 0x000C39 },                                       /* 0C35-0C39 */
+  { 0x000C41, 0x000C44 },                                       /* 0C41-0C44 */
+  { 0x000C60, 0x000C61 },                                       /* 0C60-0C61 */
+  { 0x000C66, 0x000C6F },                                       /* 0C66-0C6F */
+  { 0x000C82, 0x000C83 },                                       /* 0C82-0C83 */
+  { 0x000C85, 0x000C8C },                                       /* 0C85-0C8C */
+  { 0x000C8E, 0x000C90 },                                       /* 0C8E-0C90 */
+  { 0x000C92, 0x000CA8 },                                       /* 0C92-0CA8 */
+  { 0x000CAA, 0x000CB3 },                                       /* 0CAA-0CB3 */
+  { 0x000CB5, 0x000CB9 },                                       /* 0CB5-0CB9 */
+  { 0x000CBE           },                                            /* 0CBE */
+  { 0x000CC0, 0x000CC4 },                                       /* 0CC0-0CC4 */
+  { 0x000CC7, 0x000CC8 },                                       /* 0CC7-0CC8 */
+  { 0x000CCA, 0x000CCB },                                       /* 0CCA-0CCB */
+  { 0x000CD5, 0x000CD6 },                                       /* 0CD5-0CD6 */
+  { 0x000CDE           },                                            /* 0CDE */
+  { 0x000CE0, 0x000CE1 },                                       /* 0CE0-0CE1 */
+  { 0x000CE6, 0x000CEF },                                       /* 0CE6-0CEF */
+  { 0x000D02, 0x000D03 },                                       /* 0D02-0D03 */
+  { 0x000D05, 0x000D0C },                                       /* 0D05-0D0C */
+  { 0x000D0E, 0x000D10 },                                       /* 0D0E-0D10 */
+  { 0x000D12, 0x000D28 },                                       /* 0D12-0D28 */
+  { 0x000D2A, 0x000D39 },                                       /* 0D2A-0D39 */
+  { 0x000D3E, 0x000D40 },                                       /* 0D3E-0D40 */
+  { 0x000D46, 0x000D48 },                                       /* 0D46-0D48 */
+  { 0x000D4A, 0x000D4C },                                       /* 0D4A-0D4C */
+  { 0x000D57           },                                            /* 0D57 */
+  { 0x000D60, 0x000D61 },                                       /* 0D60-0D61 */
+  { 0x000D66, 0x000D6F },                                       /* 0D66-0D6F */
+  { 0x000D82, 0x000D83 },                                       /* 0D82-0D83 */
+  { 0x000D85, 0x000D96 },                                       /* 0D85-0D96 */
+  { 0x000D9A, 0x000DB1 },                                       /* 0D9A-0DB1 */
+  { 0x000DB3, 0x000DBB },                                       /* 0DB3-0DBB */
+  { 0x000DBD           },                                            /* 0DBD */
+  { 0x000DC0, 0x000DC6 },                                       /* 0DC0-0DC6 */
+  { 0x000DCF, 0x000DD1 },                                       /* 0DCF-0DD1 */
+  { 0x000DD8, 0x000DDF },                                       /* 0DD8-0DDF */
+  { 0x000DF2, 0x000DF4 },                                       /* 0DF2-0DF4 */
+  { 0x000E01, 0x000E30 },                                       /* 0E01-0E30 */
+  { 0x000E32, 0x000E33 },                                       /* 0E32-0E33 */
+  { 0x000E40, 0x000E46 },                                       /* 0E40-0E46 */
+  { 0x000E4F, 0x000E5B },                                       /* 0E4F-0E5B */
+  { 0x000E81, 0x000E82 },                                       /* 0E81-0E82 */
+  { 0x000E84           },                                            /* 0E84 */
+  { 0x000E87, 0x000E88 },                                       /* 0E87-0E88 */
+  { 0x000E8A           },                                            /* 0E8A */
+  { 0x000E8D           },                                            /* 0E8D */
+  { 0x000E94, 0x000E97 },                                       /* 0E94-0E97 */
+  { 0x000E99, 0x000E9F },                                       /* 0E99-0E9F */
+  { 0x000EA1, 0x000EA3 },                                       /* 0EA1-0EA3 */
+  { 0x000EA5           },                                            /* 0EA5 */
+  { 0x000EA7           },                                            /* 0EA7 */
+  { 0x000EAA, 0x000EAB },                                       /* 0EAA-0EAB */
+  { 0x000EAD, 0x000EB0 },                                       /* 0EAD-0EB0 */
+  { 0x000EB2, 0x000EB3 },                                       /* 0EB2-0EB3 */
+  { 0x000EBD           },                                            /* 0EBD */
+  { 0x000EC0, 0x000EC4 },                                       /* 0EC0-0EC4 */
+  { 0x000EC6           },                                            /* 0EC6 */
+  { 0x000ED0, 0x000ED9 },                                       /* 0ED0-0ED9 */
+  { 0x000EDC, 0x000EDD },                                       /* 0EDC-0EDD */
+  { 0x000F00, 0x000F17 },                                       /* 0F00-0F17 */
+  { 0x000F1A, 0x000F34 },                                       /* 0F1A-0F34 */
+  { 0x000F36           },                                            /* 0F36 */
+  { 0x000F38           },                                            /* 0F38 */
+  { 0x000F3E, 0x000F47 },                                       /* 0F3E-0F47 */
+  { 0x000F49, 0x000F6A },                                       /* 0F49-0F6A */
+  { 0x000F7F           },                                            /* 0F7F */
+  { 0x000F85           },                                            /* 0F85 */
+  { 0x000F88, 0x000F8B },                                       /* 0F88-0F8B */
+  { 0x000FBE, 0x000FC5 },                                       /* 0FBE-0FC5 */
+  { 0x000FC7, 0x000FCC },                                       /* 0FC7-0FCC */
+  { 0x000FCF           },                                            /* 0FCF */
+  { 0x001000, 0x001021 },                                       /* 1000-1021 */
+  { 0x001023, 0x001027 },                                       /* 1023-1027 */
+  { 0x001029, 0x00102A },                                       /* 1029-102A */
+  { 0x00102C           },                                            /* 102C */
+  { 0x001031           },                                            /* 1031 */
+  { 0x001038           },                                            /* 1038 */
+  { 0x001040, 0x001057 },                                       /* 1040-1057 */
+  { 0x0010A0, 0x0010C5 },                                       /* 10A0-10C5 */
+  { 0x0010D0, 0x0010F8 },                                       /* 10D0-10F8 */
+  { 0x0010FB           },                                            /* 10FB */
+  { 0x001100, 0x001159 },                                       /* 1100-1159 */
+  { 0x00115F, 0x0011A2 },                                       /* 115F-11A2 */
+  { 0x0011A8, 0x0011F9 },                                       /* 11A8-11F9 */
+  { 0x001200, 0x001206 },                                       /* 1200-1206 */
+  { 0x001208, 0x001246 },                                       /* 1208-1246 */
+  { 0x001248           },                                            /* 1248 */
+  { 0x00124A, 0x00124D },                                       /* 124A-124D */
+  { 0x001250, 0x001256 },                                       /* 1250-1256 */
+  { 0x001258           },                                            /* 1258 */
+  { 0x00125A, 0x00125D },                                       /* 125A-125D */
+  { 0x001260, 0x001286 },                                       /* 1260-1286 */
+  { 0x001288           },                                            /* 1288 */
+  { 0x00128A, 0x00128D },                                       /* 128A-128D */
+  { 0x001290, 0x0012AE },                                       /* 1290-12AE */
+  { 0x0012B0           },                                            /* 12B0 */
+  { 0x0012B2, 0x0012B5 },                                       /* 12B2-12B5 */
+  { 0x0012B8, 0x0012BE },                                       /* 12B8-12BE */
+  { 0x0012C0           },                                            /* 12C0 */
+  { 0x0012C2, 0x0012C5 },                                       /* 12C2-12C5 */
+  { 0x0012C8, 0x0012CE },                                       /* 12C8-12CE */
+  { 0x0012D0, 0x0012D6 },                                       /* 12D0-12D6 */
+  { 0x0012D8, 0x0012EE },                                       /* 12D8-12EE */
+  { 0x0012F0, 0x00130E },                                       /* 12F0-130E */
+  { 0x001310           },                                            /* 1310 */
+  { 0x001312, 0x001315 },                                       /* 1312-1315 */
+  { 0x001318, 0x00131E },                                       /* 1318-131E */
+  { 0x001320, 0x001346 },                                       /* 1320-1346 */
+  { 0x001348, 0x00135A },                                       /* 1348-135A */
+  { 0x001361, 0x00137C },                                       /* 1361-137C */
+  { 0x0013A0, 0x0013F4 },                                       /* 13A0-13F4 */
+  { 0x001401, 0x001676 },                                       /* 1401-1676 */
+  { 0x001681, 0x00169A },                                       /* 1681-169A */
+  { 0x0016A0, 0x0016F0 },                                       /* 16A0-16F0 */
+  { 0x001700, 0x00170C },                                       /* 1700-170C */
+  { 0x00170E, 0x001711 },                                       /* 170E-1711 */
+  { 0x001720, 0x001731 },                                       /* 1720-1731 */
+  { 0x001735, 0x001736 },                                       /* 1735-1736 */
+  { 0x001740, 0x001751 },                                       /* 1740-1751 */
+  { 0x001760, 0x00176C },                                       /* 1760-176C */
+  { 0x00176E, 0x001770 },                                       /* 176E-1770 */
+  { 0x001780, 0x0017B6 },                                       /* 1780-17B6 */
+  { 0x0017BE, 0x0017C5 },                                       /* 17BE-17C5 */
+  { 0x0017C7, 0x0017C8 },                                       /* 17C7-17C8 */
+  { 0x0017D4, 0x0017DA },                                       /* 17D4-17DA */
+  { 0x0017DC           },                                            /* 17DC */
+  { 0x0017E0, 0x0017E9 },                                       /* 17E0-17E9 */
+  { 0x001810, 0x001819 },                                       /* 1810-1819 */
+  { 0x001820, 0x001877 },                                       /* 1820-1877 */
+  { 0x001880, 0x0018A8 },                                       /* 1880-18A8 */
+  { 0x001E00, 0x001E9B },                                       /* 1E00-1E9B */
+  { 0x001EA0, 0x001EF9 },                                       /* 1EA0-1EF9 */
+  { 0x001F00, 0x001F15 },                                       /* 1F00-1F15 */
+  { 0x001F18, 0x001F1D },                                       /* 1F18-1F1D */
+  { 0x001F20, 0x001F45 },                                       /* 1F20-1F45 */
+  { 0x001F48, 0x001F4D },                                       /* 1F48-1F4D */
+  { 0x001F50, 0x001F57 },                                       /* 1F50-1F57 */
+  { 0x001F59           },                                            /* 1F59 */
+  { 0x001F5B           },                                            /* 1F5B */
+  { 0x001F5D           },                                            /* 1F5D */
+  { 0x001F5F, 0x001F7D },                                       /* 1F5F-1F7D */
+  { 0x001F80, 0x001FB4 },                                       /* 1F80-1FB4 */
+  { 0x001FB6, 0x001FBC },                                       /* 1FB6-1FBC */
+  { 0x001FBE           },                                            /* 1FBE */
+  { 0x001FC2, 0x001FC4 },                                       /* 1FC2-1FC4 */
+  { 0x001FC6, 0x001FCC },                                       /* 1FC6-1FCC */
+  { 0x001FD0, 0x001FD3 },                                       /* 1FD0-1FD3 */
+  { 0x001FD6, 0x001FDB },                                       /* 1FD6-1FDB */
+  { 0x001FE0, 0x001FEC },                                       /* 1FE0-1FEC */
+  { 0x001FF2, 0x001FF4 },                                       /* 1FF2-1FF4 */
+  { 0x001FF6, 0x001FFC },                                       /* 1FF6-1FFC */
+  { 0x00200E           },                                            /* 200E */
+  { 0x002071           },                                            /* 2071 */
+  { 0x00207F           },                                            /* 207F */
+  { 0x002102           },                                            /* 2102 */
+  { 0x002107           },                                            /* 2107 */
+  { 0x00210A, 0x002113 },                                       /* 210A-2113 */
+  { 0x002115           },                                            /* 2115 */
+  { 0x002119, 0x00211D },                                       /* 2119-211D */
+  { 0x002124           },                                            /* 2124 */
+  { 0x002126           },                                            /* 2126 */
+  { 0x002128           },                                            /* 2128 */
+  { 0x00212A, 0x00212D },                                       /* 212A-212D */
+  { 0x00212F, 0x002131 },                                       /* 212F-2131 */
+  { 0x002133, 0x002139 },                                       /* 2133-2139 */
+  { 0x00213D, 0x00213F },                                       /* 213D-213F */
+  { 0x002145, 0x002149 },                                       /* 2145-2149 */
+  { 0x002160, 0x002183 },                                       /* 2160-2183 */
+  { 0x002336, 0x00237A },                                       /* 2336-237A */
+  { 0x002395           },                                            /* 2395 */
+  { 0x00249C, 0x0024E9 },                                       /* 249C-24E9 */
+  { 0x003005, 0x003007 },                                       /* 3005-3007 */
+  { 0x003021, 0x003029 },                                       /* 3021-3029 */
+  { 0x003031, 0x003035 },                                       /* 3031-3035 */
+  { 0x003038, 0x00303C },                                       /* 3038-303C */
+  { 0x003041, 0x003096 },                                       /* 3041-3096 */
+  { 0x00309D, 0x00309F },                                       /* 309D-309F */
+  { 0x0030A1, 0x0030FA },                                       /* 30A1-30FA */
+  { 0x0030FC, 0x0030FF },                                       /* 30FC-30FF */
+  { 0x003105, 0x00312C },                                       /* 3105-312C */
+  { 0x003131, 0x00318E },                                       /* 3131-318E */
+  { 0x003190, 0x0031B7 },                                       /* 3190-31B7 */
+  { 0x0031F0, 0x00321C },                                       /* 31F0-321C */
+  { 0x003220, 0x003243 },                                       /* 3220-3243 */
+  { 0x003260, 0x00327B },                                       /* 3260-327B */
+  { 0x00327F, 0x0032B0 },                                       /* 327F-32B0 */
+  { 0x0032C0, 0x0032CB },                                       /* 32C0-32CB */
+  { 0x0032D0, 0x0032FE },                                       /* 32D0-32FE */
+  { 0x003300, 0x003376 },                                       /* 3300-3376 */
+  { 0x00337B, 0x0033DD },                                       /* 337B-33DD */
+  { 0x0033E0, 0x0033FE },                                       /* 33E0-33FE */
+  { 0x003400, 0x004DB5 },                                       /* 3400-4DB5 */
+  { 0x004E00, 0x009FA5 },                                       /* 4E00-9FA5 */
+  { 0x00A000, 0x00A48C },                                       /* A000-A48C */
+  { 0x00AC00, 0x00D7A3 },                                       /* AC00-D7A3 */
+  { 0x00D800, 0x00FA2D },                                       /* D800-FA2D */
+  { 0x00FA30, 0x00FA6A },                                       /* FA30-FA6A */
+  { 0x00FB00, 0x00FB06 },                                       /* FB00-FB06 */
+  { 0x00FB13, 0x00FB17 },                                       /* FB13-FB17 */
+  { 0x00FF21, 0x00FF3A },                                       /* FF21-FF3A */
+  { 0x00FF41, 0x00FF5A },                                       /* FF41-FF5A */
+  { 0x00FF66, 0x00FFBE },                                       /* FF66-FFBE */
+  { 0x00FFC2, 0x00FFC7 },                                       /* FFC2-FFC7 */
+  { 0x00FFCA, 0x00FFCF },                                       /* FFCA-FFCF */
+  { 0x00FFD2, 0x00FFD7 },                                       /* FFD2-FFD7 */
+  { 0x00FFDA, 0x00FFDC },                                       /* FFDA-FFDC */
+  { 0x010300, 0x01031E },                                     /* 10300-1031E */
+  { 0x010320, 0x010323 },                                     /* 10320-10323 */
+  { 0x010330, 0x01034A },                                     /* 10330-1034A */
+  { 0x010400, 0x010425 },                                     /* 10400-10425 */
+  { 0x010428, 0x01044D },                                     /* 10428-1044D */
+  { 0x01D000, 0x01D0F5 },                                     /* 1D000-1D0F5 */
+  { 0x01D100, 0x01D126 },                                     /* 1D100-1D126 */
+  { 0x01D12A, 0x01D166 },                                     /* 1D12A-1D166 */
+  { 0x01D16A, 0x01D172 },                                     /* 1D16A-1D172 */
+  { 0x01D183, 0x01D184 },                                     /* 1D183-1D184 */
+  { 0x01D18C, 0x01D1A9 },                                     /* 1D18C-1D1A9 */
+  { 0x01D1AE, 0x01D1DD },                                     /* 1D1AE-1D1DD */
+  { 0x01D400, 0x01D454 },                                     /* 1D400-1D454 */
+  { 0x01D456, 0x01D49C },                                     /* 1D456-1D49C */
+  { 0x01D49E, 0x01D49F },                                     /* 1D49E-1D49F */
+  { 0x01D4A2           },                                           /* 1D4A2 */
+  { 0x01D4A5, 0x01D4A6 },                                     /* 1D4A5-1D4A6 */
+  { 0x01D4A9, 0x01D4AC },                                     /* 1D4A9-1D4AC */
+  { 0x01D4AE, 0x01D4B9 },                                     /* 1D4AE-1D4B9 */
+  { 0x01D4BB           },                                           /* 1D4BB */
+  { 0x01D4BD, 0x01D4C0 },                                     /* 1D4BD-1D4C0 */
+  { 0x01D4C2, 0x01D4C3 },                                     /* 1D4C2-1D4C3 */
+  { 0x01D4C5, 0x01D505 },                                     /* 1D4C5-1D505 */
+  { 0x01D507, 0x01D50A },                                     /* 1D507-1D50A */
+  { 0x01D50D, 0x01D514 },                                     /* 1D50D-1D514 */
+  { 0x01D516, 0x01D51C },                                     /* 1D516-1D51C */
+  { 0x01D51E, 0x01D539 },                                     /* 1D51E-1D539 */
+  { 0x01D53B, 0x01D53E },                                     /* 1D53B-1D53E */
+  { 0x01D540, 0x01D544 },                                     /* 1D540-1D544 */
+  { 0x01D546           },                                           /* 1D546 */
+  { 0x01D54A, 0x01D550 },                                     /* 1D54A-1D550 */
+  { 0x01D552, 0x01D6A3 },                                     /* 1D552-1D6A3 */
+  { 0x01D6A8, 0x01D7C9 },                                     /* 1D6A8-1D7C9 */
+  { 0x020000, 0x02A6D6 },                                     /* 20000-2A6D6 */
+  { 0x02F800, 0x02FA1D },                                     /* 2F800-2FA1D */
+  { 0x0F0000, 0x0FFFFD },                                     /* F0000-FFFFD */
+  { 0x100000, 0x10FFFD },                                   /* 100000-10FFFD */
+  { 0 },
+};
+
diff --git a/lib/contrib/stringprep.c b/lib/contrib/stringprep.c
new file mode 100644 (file)
index 0000000..497b5bf
--- /dev/null
@@ -0,0 +1,675 @@
+/* stringprep.c --- Core stringprep implementation.
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "stringprep.h"
+
+const Stringprep_profiles stringprep_profiles[] = {
+  {NULL, NULL}
+};
+
+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: a #Stringprep_profile_flags value, 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 values, or 0.
+ *
+ * The @profile contain the #Stringprep_profile 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
+ *   #Stringprep_rc 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: a #Stringprep_profile_flags value, 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 values, or 0.
+ *
+ * The @profile contain the #Stringprep_profile 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
+ *   #Stringprep_rc 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: a #Stringprep_profile_flags value, 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 values, or 0.
+ *
+ * The @profile contain the #Stringprep_profile 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
+    {
+      uint32_t *newp;
+
+      if (ucs4)
+       free (ucs4);
+      ucs4 = stringprep_utf8_to_ucs4 (in, -1, &ucs4len);
+      maxucs4len = ucs4len + adducs4len;
+      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: a #Stringprep_profile_flags value, 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 values, 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
+    {
+      if (str)
+       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 bidirection 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.
+ **/
diff --git a/lib/contrib/stringprep.h b/lib/contrib/stringprep.h
new file mode 100644 (file)
index 0000000..d182fad
--- /dev/null
@@ -0,0 +1,181 @@
+/* stringprep.h --- Header file for stringprep functions.             -*- c -*-
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef _STRINGPREP_H
+#define _STRINGPREP_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stddef.h>            /* size_t */
+#include <stdlib.h>
+
+#include "silcincludes.h"
+
+#ifndef uint32_t
+#define uint32_t SilcUInt32
+#endif
+#ifndef ssize_t
+#define ssize_t int
+#endif
+#ifndef uint16_t
+#define uint16_t SilcUInt16
+#endif
+#ifndef int16_t
+#define int16_t SilcInt16
+#endif
+
+#define STRINGPREP_VERSION "0.5.9"
+
+/* 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[];
+
+  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_strerror (Stringprep_rc rc);
+
+  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, int len,
+                                           size_t * items_written);
+  extern char *stringprep_ucs4_to_utf8 (const uint32_t * str, int len,
+                                       size_t * items_read,
+                                       size_t * items_written);
+
+  extern char *stringprep_utf8_nfkc_normalize (const char *str, int len);
+  extern uint32_t *stringprep_ucs4_nfkc_normalize (uint32_t * str,
+                                                  int 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 */
index 77a7f9e54e1ddac4a79f1a0c2d287a87d9ce1ae2..d03634264b7eed45ffa3fec5cbb67041d5adb456 100644 (file)
@@ -10,7 +10,7 @@ automatically generated links to that list. -->
 <b>Resource Links</b>
 <br />
 <a href="http://silcnet.org"><img src="box.gif" border="0" alt="">SILC Project Website</a><br />
-<a href="http://silcnet.org/?page=docs"><img src="box.gif" border="0" alt="">SILC Protocol Documentation</a><br />
-<a href="http://silcnet.org/?page=whitepaper"><img src="box.gif" border="0" alt="">SILC White Paper</a><br />
-<a href="http://silcnet.org/?page=faq"><img src="box.gif" border="0" alt="">SILC FAQ</a><br />
+<a href="http://silcnet.org/support/documentation/"><img src="box.gif" border="0" alt="">SILC Protocol Documentation</a><br />
+<a href="http://silcnet.org/support/documentation/wp/"><img src="box.gif" border="0" alt="">SILC White Paper</a><br />
+<a href="http://silcnet.org/support/faq/"><img src="box.gif" border="0" alt="">SILC FAQs</a><br />
 
index 2d15f87181b300875745641ebf8a6f3d92e3edb8..3cdac009f1ca6d22258eef8a0da8cad6e53e553e 100644 (file)
@@ -7,7 +7,7 @@
 <br />
 <small>
 Version: @VERSION@<br />
-Copyright &copy; 1997 - 2003 The SILC Project<br />
+Copyright &copy; 1997 - 2004 The SILC Project<br />
 Updated: @DATE@
 </small>
 <br /><br /><br />
index fa9019b08ed3c8be09d54d3c956d99d70ef239cc..a38209e9df6b57aa618222c32ed85b97a7acfb17 100644 (file)
@@ -153,7 +153,11 @@ const SilcClientID *old_client_id
 <td><small>
 Returns the list of channel in the SILC network. Each call of command reply
 returns one channel. This means that the command reply is called multiple
-times to return list of channels.  The 'channel_topic' may be NULL.
+times to return list of channels.  The 'channel', 'channel_name' and
+'channel_topic' may be NULL.  However, the 'channel' and 'channel_name'
+are NULL only if there are no channels in the network.  In this case
+this reply is called once with all arguments set to NULL.  Application
+must be able to handle this situation correctly.
 </td>
 <td width="50%"><small>SilcChannelEntry channel, char *channel_name,
 char *channel_topic, SilcUInt32 user_count
@@ -261,7 +265,7 @@ keys, it may be NULL.
 SilcUInt32 channel_mode, int ignored, SilcBuffer key_payload, NULL, NULL,
 char *topic, char *hmac_name, SilcUInt32 list_count, SilcBuffer client_id_list,
 SilcBuffer client_mode_list, SilcPublicKey founder_key,
-SilcBuffer channel_pubkeys
+SilcBuffer channel_pubkeys, SilcUint32 user_limit
 </td>
 </tr>
 
@@ -294,7 +298,8 @@ Argument List Payload where each argument includes one Public Key
 Payload.
 </td>
 <td width="50%"><small>SilcChannelEntry channel, SilcUInt32 mode,
-SilcPublicKey founder_key, SilcBuffer channel_pubkeys
+SilcPublicKey founder_key, SilcBuffer channel_pubkeys,
+SilcUint32 user_limit
 </td>
 </tr>
 
index 3c9061162a7ed62398c49d11a498994930366da7..cc22145398edfbee0fbc9bbdb92fa207e9b2b415 100644 (file)
@@ -264,7 +264,8 @@ happened for the 'watched_client' (for example
 SILC_NOTIFY_TYPE_NICK_CHANGE if the client changed their nickname).
 </td>
 <td width="50%"><small>SilcClientEntry watched_client, char *new_nickname,
-SilcUInt32 user_mode, SilcNotifyType notification
+SilcUInt32 user_mode, SilcNotifyType notification, SilcPublicKey 
+public_key
 </td>
 </tr>
 
diff --git a/lib/doc/silcclient_unicode.html b/lib/doc/silcclient_unicode.html
new file mode 100644 (file)
index 0000000..3470b5e
--- /dev/null
@@ -0,0 +1,40 @@
+<big><b>Unicode and UTF-8 Strings in Client Library</b></big>
+
+<br />&nbsp;<br />
+This document describes how the client library handles UTF-8 encoded
+strings.  By default all strings in the SILC protocol are UTF-8 encoded.
+All strings that are sent to server and strings that are received from the
+server are always UTF-8 encoded.  It is application's responsibility to
+render the strings as well as possible on the user interface.
+
+<br />&nbsp;<br />
+Exception to these strings are messages sent and received in
+<a href="silcmessage-SilcMessagePayload.html">Message Payload</a>, which
+can include practically any kind of strings with any kind of character
+encodings, and binary data also.  If UTF-8 encoded message is sent
+or received it is indicated with the SILC_MESSAGE_FLAG_UTF8, and
+application can render the messages accordingly.
+
+<br />&nbsp;<br />
+Other strings are always UTF-8 encoded and application needs to decode
+the strings to other character encoding if application does not support
+UTF-8 rendering on user interface.  Also strings application sends to
+library, such as, nicknames, channel names, server names, host names,
+topic srings, any command argument, etc. must always be UTF-8 encoded
+before they are sent to the library.  The <a href="silcutf8.html">UTF-8
+routines</a> help the application developer to encode and decode
+UTF-8 strings.
+
+<br />&nbsp;<br />
+The client library does not ever encode or decode strings to or from the
+current locale.  The library always expects that all strings it receives
+from application are already UTF-8 encoded.  The library may validate
+certain UTF-8 strings and return error if needed.  Server may also
+send errors in command reply if strings are not encoded properly.
+
+<br />&nbsp;<br />
+Nicknames and channel names in SILC are also UTF-8 encoded and can
+include practically any kind of letters, numbers and punctuation
+marks.  Control characters and other special characters are not allowed
+in nickname strings, and application never receives such nicknames
+or channel names from the library.
diff --git a/lib/silc.pc.in b/lib/silc.pc.in
new file mode 100644 (file)
index 0000000..0a1a2bc
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE@
+Description: SILC Library
+Version: @VERSION@
+Conflicts: libsilc <= 0.9.12
+Libs: @LIBS@ -L${libdir} -lsilc
+Cflags: -I${includedir}
+
diff --git a/lib/silcclient.pc.in b/lib/silcclient.pc.in
new file mode 100644 (file)
index 0000000..cd5854f
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE@ (client library)
+Description: SILC Client Library
+Version: @VERSION@
+Conflicts: libsilc <= 0.9.12
+Requires: silc = @VERSION@
+Libs: @LIBS@ -L${libdir} -lsilcclient
+Cflags: -I${includedir}
+
index d61bcfe7a4e4752daf2832585500ff9b88269244..a4fad88df39d8f60f23e4afd8314a82a9f1d6823 100644 (file)
@@ -5,6 +5,7 @@
 @LINK=command_reply_args.html:Arguments for <b>command_reply</b> Client Operation
 @LINK=silcstatus_args.html:SilcStatus Error Arguments in <b>command_reply</b> Client Operation
 @LINK=notifyargs.html:Arguments for <b>notify</b> Client Operation
+@LINK=silcclient_unicode.html:Unicode and UTF-8 Strings in Client Library
 @LINK=silcclient.html:Client Library Interface Reference
 -->
 
@@ -17,7 +18,7 @@
 <b>Introduction</b>
 
 <br /><br />
-SILC Client Library is SILC Client implementation without the actual user 
+SILC Client Library is SILC Client implementation without the actual user
 interface. The library uses common and core components of SILC protocol from
 lib/silccore library and normal utility routines from lib/silcutil library.
 The library has been designed to be complete SILC Client implementation
similarity index 76%
rename from lib/silcclient/Makefile.am
rename to lib/silcclient/Makefile.ad
index 103e09e59bb1d61541d7489cbd7ff9bd0e5e60bd..b85ac5a9f083af64a9c746681ad9cfa08c4ddbfc 100644 (file)
@@ -1,14 +1,13 @@
 #
 #  Makefile.am
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -34,7 +33,7 @@ libsilcclient_la_SOURCES = \
        idlist.c \
        protocol.c
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS=       \
        client.h        \
        command.h       \
@@ -42,8 +41,10 @@ include_HEADERS=     \
        idlist.h        \
        protocol.h      \
        silcclient.h
-endif
 
-EXTRA_DIST = *.h client_ops_example.c
+SILC_EXTRA_DIST = client_ops_example.c
+#endif SILC_DIST_TOOLKIT
+
+EXTRA_DIST = *.h $(SILC_EXTRA_DIST)
 
 include $(top_srcdir)/Makefile.defines.in
index 9fc554bf5568f91e2d7e4033da3446747e861a33..d4546038895c4c10d7c0c85f9b1d234e72f609e5 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -88,10 +88,12 @@ void silc_client_free(SilcClient client)
     if (client->rng)
       silc_rng_free(client->rng);
 
-    silc_cipher_unregister_all();
-    silc_pkcs_unregister_all();
-    silc_hash_unregister_all();
-    silc_hmac_unregister_all();
+    if (!client->internal->params->dont_register_crypto_library) {
+      silc_cipher_unregister_all();
+      silc_pkcs_unregister_all();
+      silc_hash_unregister_all();
+      silc_hmac_unregister_all();
+    }
 
     silc_hash_free(client->md5hash);
     silc_hash_free(client->sha1hash);
@@ -118,13 +120,37 @@ bool silc_client_init(SilcClient client)
   assert(client->hostname);
   assert(client->realname);
 
-  /* Initialize the crypto library.  If application has done this already
-     this has no effect.  Also, we will not be overriding something
-     application might have registered earlier. */
-  silc_cipher_register_default();
-  silc_pkcs_register_default();
-  silc_hash_register_default();
-  silc_hmac_register_default();
+  /* Validate essential strings */
+  if (client->nickname)
+    if (!silc_identifier_verify(client->nickname, strlen(client->nickname),
+                               SILC_STRING_UTF8, 128)) {
+      SILC_LOG_ERROR(("Malformed nickname '%s'", client->nickname));
+      return FALSE;
+    }
+  if (!silc_identifier_verify(client->username, strlen(client->username),
+                             SILC_STRING_UTF8, 128)) {
+    SILC_LOG_ERROR(("Malformed username '%s'", client->username));
+    return FALSE;
+  }
+  if (!silc_identifier_verify(client->hostname, strlen(client->hostname),
+                             SILC_STRING_UTF8, 256)) {
+    SILC_LOG_ERROR(("Malformed hostname '%s'", client->hostname));
+    return FALSE;
+  }
+  if (!silc_utf8_valid(client->realname, strlen(client->realname))) {
+    SILC_LOG_ERROR(("Malformed realname '%s'", client->realname));
+    return FALSE;
+  }
+
+  if (!client->internal->params->dont_register_crypto_library) {
+    /* Initialize the crypto library.  If application has done this already
+       this has no effect.  Also, we will not be overriding something
+       application might have registered earlier. */
+    silc_cipher_register_default();
+    silc_pkcs_register_default();
+    silc_hash_register_default();
+    silc_hmac_register_default();
+  }
 
   /* Initialize hash functions for client to use */
   silc_hash_alloc("md5", &client->md5hash);
@@ -201,12 +227,6 @@ void silc_client_run_one(SilcClient client)
   silc_schedule_one(client->schedule, 0);
 }
 
-static void silc_client_entry_destructor(SilcIDCache cache,
-                                        SilcIDCacheEntry entry)
-{
-  silc_free(entry->name);
-}
-
 /* Allocates and adds new connection to the client. This adds the allocated
    connection to the connection table and returns a pointer to it. A client
    can have multiple connections to multiple servers. Every connection must
@@ -234,9 +254,11 @@ silc_client_add_connection(SilcClient client,
   conn->remote_port = port;
   conn->context = context;
   conn->internal->client_cache =
-    silc_idcache_alloc(0, SILC_ID_CLIENT, silc_client_entry_destructor);
-  conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL);
-  conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL);
+    silc_idcache_alloc(0, SILC_ID_CLIENT, NULL, FALSE, TRUE);
+  conn->internal->channel_cache = silc_idcache_alloc(0, SILC_ID_CHANNEL, NULL,
+                                                    FALSE, TRUE);
+  conn->internal->server_cache = silc_idcache_alloc(0, SILC_ID_SERVER, NULL,
+                                                   FALSE, TRUE);
   conn->internal->pending_commands = silc_dlist_init();
   conn->internal->ftp_sessions = silc_dlist_init();
 
@@ -572,7 +594,7 @@ SILC_TASK_CALLBACK(silc_client_connect_failure)
   SilcClient client = (SilcClient)ctx->client;
 
   client->internal->ops->connected(client, ctx->sock->user_data,
-                                  SILC_CLIENT_CONN_ERROR);
+                                  SILC_CLIENT_CONN_ERROR_KE);
   if (ctx->packet)
     silc_packet_context_free(ctx->packet);
   silc_free(ctx);
@@ -587,8 +609,7 @@ SILC_TASK_CALLBACK(silc_client_connect_failure_auth)
     (SilcClientConnAuthInternalContext *)context;
   SilcClient client = (SilcClient)ctx->client;
 
-  client->internal->ops->connected(client, ctx->sock->user_data,
-                                  SILC_CLIENT_CONN_ERROR);
+  client->internal->ops->connected(client, ctx->sock->user_data, ctx->status);
   silc_free(ctx);
 }
 
@@ -636,7 +657,8 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_start)
       silc_free(ctx);
 
       /* Notify application of failure */
-      client->internal->ops->connected(client, conn, SILC_CLIENT_CONN_ERROR);
+      client->internal->ops->connected(client, conn,
+                                      SILC_CLIENT_CONN_ERROR_TIMEOUT);
     }
     return;
   }
@@ -788,6 +810,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
     /* Error occured during protocol */
     SILC_LOG_DEBUG(("Error during authentication protocol"));
+    ctx->status = SILC_CLIENT_CONN_ERROR_AUTH;
     goto err;
   }
 
@@ -799,12 +822,15 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
     unsigned char *old_id;
     SilcUInt16 old_id_len;
 
-    if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len))
+    if (!silc_client_process_detach_data(client, conn, &old_id, &old_id_len)) {
+      ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
       goto err;
+    }
 
     old_client_id = silc_id_str2id(old_id, old_id_len, SILC_ID_CLIENT);
     if (!old_client_id) {
       silc_free(old_id);
+      ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
       goto err;
     }
 
@@ -817,6 +843,7 @@ SILC_TASK_CALLBACK(silc_client_connect_to_server_final)
     if (!auth) {
       silc_free(old_client_id);
       silc_free(old_id);
+      ctx->status = SILC_CLIENT_CONN_ERROR_RESUME;
       goto err;
     }
 
@@ -1056,8 +1083,6 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
 
     /* Parse the incoming packet type */
     silc_client_packet_parse_type(client, sock, packet);
-    silc_packet_context_free(packet);
-    silc_free(parser_context);
 
     /* Reprocess the buffer since we'll return FALSE. This is because
        the `conn->internal->receive_key' might have become valid by processing
@@ -1071,6 +1096,9 @@ static bool silc_client_packet_parse(SilcPacketParserContext *parser_context,
       silc_packet_receive_process(sock, FALSE, NULL, NULL, 0,
                                  silc_client_packet_parse, client);
 
+    silc_packet_context_free(packet);
+    silc_free(parser_context);
+
     return FALSE;
   }
 
@@ -1161,8 +1189,9 @@ void silc_client_packet_parse_type(SilcClient client,
 
   case SILC_PACKET_PRIVATE_MESSAGE_KEY:
     /*
-     * Received private message key
+     * Received private message key indicator
      */
+    silc_client_private_message_key(client, sock, packet);
     break;
 
   case SILC_PACKET_COMMAND:
@@ -1495,8 +1524,21 @@ void silc_client_packet_queue_purge(SilcClient client,
                                    SilcSocketConnection sock)
 {
   if (sock && SILC_IS_OUTBUF_PENDING(sock) &&
-      (SILC_IS_DISCONNECTED(sock) == FALSE)) {
-    silc_packet_send(sock, TRUE);
+      !(SILC_IS_DISCONNECTED(sock))) {
+    int ret;
+
+    ret = silc_packet_send(sock, TRUE);
+    if (ret == -2) {
+      if (sock->outbuf && sock->outbuf->len > 0) {
+       /* Couldn't send all data, put the queue back up, we'll send
+          rest later. */
+       SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT(client->schedule, sock->sock);
+       SILC_SET_OUTBUF_PENDING(sock);
+       return;
+      }
+    }
+
+    /* Purged all data */
     SILC_UNSET_OUTBUF_PENDING(sock);
     SILC_CLIENT_SET_CONNECTION_FOR_INPUT(client->schedule, sock->sock);
     silc_buffer_clear(sock->outbuf);
@@ -1671,7 +1713,7 @@ static void silc_client_resume_session_cb(SilcClient client,
   /* Notify application that connection is created to server */
   client->internal->ops->connected(client, conn, success ?
                                   SILC_CLIENT_CONN_SUCCESS_RESUME :
-                                  SILC_CLIENT_CONN_ERROR);
+                                  SILC_CLIENT_CONN_ERROR_RESUME);
 
   if (success) {
     /* Issue INFO command to fetch the real server name and server
@@ -1696,6 +1738,7 @@ void silc_client_receive_new_id(SilcClient client,
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
   int connecting = FALSE;
   SilcClientID *client_id = silc_id_payload_get_id(idp);
+  char *nickname;
 
   if (!conn->local_entry)
     connecting = TRUE;
@@ -1738,9 +1781,14 @@ void silc_client_receive_new_id(SilcClient client,
                                                        NULL, NULL, NULL,
                                                        TRUE);
 
-  /* Put it to the ID cache */
-  silc_idcache_add(conn->internal->client_cache,
-                  strdup(conn->nickname), conn->local_id,
+  /* Normalize nickname */
+  nickname = silc_identifier_check(conn->nickname, strlen(conn->nickname),
+                                  SILC_STRING_UTF8, 128, NULL);
+  if (!nickname)
+    return;
+
+    /* Put it to the ID cache */
+  silc_idcache_add(conn->internal->client_cache, nickname, conn->local_id,
                   (void *)conn->local_entry, 0, NULL);
 
   if (connecting) {
@@ -1759,7 +1807,8 @@ void silc_client_receive_new_id(SilcClient client,
     if (!conn->internal->params.detach_data) {
       /* Send NICK command if the nickname was set by the application (and is
         not same as the username). Send this with little timeout. */
-      if (client->nickname && strcmp(client->nickname, client->username))
+      if (client->nickname &&
+         !silc_utf8_strcasecmp(client->nickname, client->username))
        silc_schedule_task_add(client->schedule, 0,
                               silc_client_send_auto_nick, conn,
                               1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
@@ -1798,7 +1847,7 @@ void silc_client_remove_from_channels(SilcClient client,
   SilcChannelUser chu;
 
   silc_hash_table_list(client_entry->channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
     silc_hash_table_del(chu->client->channels, chu->channel);
     silc_hash_table_del(chu->channel->user_list, chu->client);
     silc_free(chu);
@@ -1821,7 +1870,7 @@ void silc_client_replace_from_channels(SilcClient client,
   SilcChannelUser chu;
 
   silc_hash_table_list(old->channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
     /* Replace client entry */
     silc_hash_table_del(chu->client->channels, chu->channel);
     silc_hash_table_del(chu->channel->user_list, chu->client);
@@ -1848,7 +1897,7 @@ void silc_client_process_failure(SilcClient client,
 
     /* Notify application */
     client->internal->ops->failure(client, sock->user_data, sock->protocol,
-                                  (void *)failure);
+                                  SILC_32_TO_PTR(failure));
   }
 }
 
index d49833f6247bbd4770e539ff4a695dea77f1bfe7..0780823abd36ae8c5ba79b6c7bdbcba7a410f33e 100644 (file)
@@ -46,11 +46,4 @@ typedef enum {
   SILC_CLIENT_STATUS_RESOLVING  = 0x0001,
 } SilcEntryStatus;
 
-/* Client and its mode on a channel */
-struct SilcChannelUserStruct {
-  SilcClientEntry client;
-  SilcUInt32 mode;
-  SilcChannelEntry channel;
-};
-
 #endif
index 65a8b03e9e86c26a61796f892aac2507032d8f1f..fc0821da6ee1268690ec88e29f023ca95909f932 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  client_attrs.c 
+  client_attrs.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -31,7 +31,7 @@ typedef struct {
 static void silc_client_attributes_process_foreach(void *key, void *context,
                                                   void *user_context)
 {
-  SilcAttribute attribute = (SilcAttribute)(SilcUInt32)key;
+  SilcAttribute attribute = (SilcAttribute)SILC_PTR_TO_32(key);
   SilcAttributePayload attr = context;
   SilcAttrForeach *f = user_context;
   const unsigned char *data;
@@ -54,6 +54,7 @@ static void silc_client_attributes_process_foreach(void *key, void *context,
   SILC_LOG_DEBUG(("Attribute %d found", attribute));
   data = silc_attribute_get_data(attr, &data_len);
 
+#if 0
   /* We replace the TIMEZONE with valid value here */
   if (attribute == SILC_ATTRIBUTE_TIMEZONE) {
     data = (const unsigned char *)silc_get_time(0);
@@ -63,6 +64,7 @@ static void silc_client_attributes_process_foreach(void *key, void *context,
                                              (void *)data, data_len);
     return;
   }
+#endif
 
   f->buffer = silc_attribute_payload_encode_data(f->buffer, attribute,
                                                 SILC_ATTRIBUTE_FLAG_VALID,
@@ -113,7 +115,7 @@ SilcBuffer silc_client_attributes_process(SilcClient client,
       continue;
 
     silc_hash_table_find_foreach(conn->internal->attrs,
-                                (void *)(SilcUInt32)attribute,
+                                SILC_32_TO_PTR(attribute),
                                 silc_client_attributes_process_foreach,
                                 &f);
   }
@@ -163,7 +165,7 @@ SilcAttributePayload silc_client_attribute_add(SilcClient client,
                            NULL, silc_client_attribute_destruct,
                            NULL, TRUE);
   silc_hash_table_add(conn->internal->attrs,
-                     (void *)(SilcUInt32)attribute, attr);
+                     SILC_32_TO_PTR(attribute), attr);
   return attr;
 }
 
@@ -177,7 +179,7 @@ static void silc_client_attribute_del_foreach(void *key, void *context,
     return;
   attribute = silc_attribute_get_attribute(attr);
   silc_hash_table_del_by_context(conn->internal->attrs,
-                                (void *)(SilcUInt32)attribute, attr);
+                                SILC_32_TO_PTR(attribute), attr);
 }
 
 /* Delete one attribute */
@@ -195,10 +197,10 @@ bool silc_client_attribute_del(SilcClient client,
   if (attr) {
     attribute = silc_attribute_get_attribute(attr);
     ret = silc_hash_table_del_by_context(conn->internal->attrs,
-                                        (void *)(SilcUInt32)attribute, attr);
+                                        SILC_32_TO_PTR(attribute), attr);
   } else if (attribute) {
     silc_hash_table_find_foreach(conn->internal->attrs,
-                                (void *)(SilcUInt32)attribute,
+                                SILC_32_TO_PTR(attribute),
                                 silc_client_attribute_del_foreach, conn);
     ret = TRUE;
   } else{
index 0d4384096b62779c95409bb0d786a5a6f8b8fd5a..b052ea23cf561512b0fd86a2a4d28809160a28a0 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -73,16 +73,18 @@ bool silc_client_send_channel_message(SilcClient client,
     return FALSE;
 
   /* Take the key to be used */
-  if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
+  if (channel->private_keys) {
     if (key) {
       /* Use key application specified */
       cipher = key->cipher;
       hmac = key->hmac;
-    } else if (channel->curr_key) {
+    } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
+              channel->curr_key) {
       /* Use current private key */
       cipher = channel->curr_key->cipher;
       hmac = channel->curr_key->hmac;
-    } else if (!channel->curr_key && channel->private_keys) {
+    } else if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY &&
+              !channel->curr_key && channel->private_keys) {
       /* Use just some private key since we don't know what to use
         and private keys are set. */
       silc_dlist_start(channel->private_keys);
@@ -184,6 +186,7 @@ bool silc_client_send_channel_message(SilcClient client,
 typedef struct {
   SilcMessagePayload payload;
   SilcChannelID *channel_id;
+  SilcChannelPrivateKey key;
 } *SilcChannelClientResolve;
 
 static void silc_client_channel_message_cb(SilcClient client,
@@ -218,7 +221,7 @@ static void silc_client_channel_message_cb(SilcClient client,
     /* Pass the message to application */
     client->internal->ops->channel_message(
                            client, conn, clients[0], channel, res->payload,
-                           silc_message_get_flags(res->payload),
+                           res->key, silc_message_get_flags(res->payload),
                            message, message_len);
   }
 
@@ -245,6 +248,7 @@ void silc_client_channel_message(SilcClient client,
   SilcClientID *client_id = NULL;
   unsigned char *message;
   SilcUInt32 message_len;
+  SilcChannelPrivateKey key = NULL;
 
   SILC_LOG_DEBUG(("Received channel message"));
 
@@ -268,7 +272,7 @@ void silc_client_channel_message(SilcClient client,
   /* If there is no channel private key then just decrypt the message
      with the channel key. If private keys are set then just go through
      all private keys and check what decrypts correctly. */
-  if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
+  if (!channel->private_keys) {
     /* Parse the channel message payload. This also decrypts the payload */
     payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE,
                                         FALSE, channel->channel_key,
@@ -304,22 +308,28 @@ void silc_client_channel_message(SilcClient client,
       if (!payload)
        goto out;
     }
-  } else if (channel->private_keys) {
-    SilcChannelPrivateKey entry;
-
-    silc_dlist_start(channel->private_keys);
-    while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
-      /* Parse the message payload. This also decrypts the payload */
-      payload = silc_message_payload_parse(buffer->data, buffer->len,
-                                          FALSE, FALSE,
-                                          entry->cipher, entry->hmac);
-      if (payload)
-       break;
-    }
-    if (entry == SILC_LIST_END)
-      goto out;
   } else {
-    goto out;
+    /* If the private key mode, however is not set on the channel then
+       try the actual channel key first before trying private keys. */
+    if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+      payload = silc_message_payload_parse(buffer->data, buffer->len, FALSE,
+                                          FALSE, channel->channel_key,
+                                          channel->hmac);
+
+    if (!payload) {
+      silc_dlist_start(channel->private_keys);
+      while ((key = silc_dlist_get(channel->private_keys))
+            != SILC_LIST_END) {
+       /* Parse the message payload. This also decrypts the payload */
+       payload = silc_message_payload_parse(buffer->data, buffer->len,
+                                            FALSE, FALSE,
+                                            key->cipher, key->hmac);
+       if (payload)
+         break;
+      }
+      if (key == SILC_LIST_END)
+       goto out;
+    }
   }
 
   /* Find client entry */
@@ -330,6 +340,7 @@ void silc_client_channel_message(SilcClient client,
     SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
     res->payload = payload;
     res->channel_id = id;
+    res->key = key;
     silc_client_get_client_by_id_resolve(client, conn, client_id, NULL,
                                         silc_client_channel_message_cb,
                                         res);
@@ -343,7 +354,7 @@ void silc_client_channel_message(SilcClient client,
   /* Pass the message to application */
   client->internal->ops->channel_message(
                             client, conn, client_entry, channel, payload,
-                            silc_message_get_flags(payload),
+                            key, silc_message_get_flags(payload),
                             message, message_len);
 
  out:
@@ -485,13 +496,12 @@ void silc_client_receive_channel_key(SilcClient client,
   silc_client_save_channel_key(client, sock->user_data, packet, NULL);
 }
 
-/* Adds private key for channel. This may be set only if the channel's mode
-   mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
-   mode is not set. When channel has private key then the messages are
-   encrypted using that key. All clients on the channel must also know the
-   key in order to decrypt the messages. However, it is possible to have
-   several private keys per one channel. In this case only some of the
-   clients on the channel may know the one key and only some the other key.
+/* Adds private key for channel. When channel has private key then the
+   messages are encrypted using that key. All clients on the channel must
+   also know the key in order to decrypt the messages. However, it is
+   possible to have several private keys per one channel. In this case
+   only some of the clients on the channel may know the one key and only
+   some the other key.
 
    If `cipher' and/or `hmac' is NULL then default values will be used
    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
@@ -515,13 +525,14 @@ void silc_client_receive_channel_key(SilcClient client,
    as channel private key. However, this API allows it. */
 
 bool silc_client_add_channel_private_key(SilcClient client,
-                                       SilcClientConnection conn,
-                                       SilcChannelEntry channel,
-                                       const char *name,
-                                       char *cipher,
-                                       char *hmac,
-                                       unsigned char *key,
-                                       SilcUInt32 key_len)
+                                        SilcClientConnection conn,
+                                        SilcChannelEntry channel,
+                                        const char *name,
+                                        char *cipher,
+                                        char *hmac,
+                                        unsigned char *key,
+                                        SilcUInt32 key_len,
+                                        SilcChannelPrivateKey *ret_key)
 {
   SilcChannelPrivateKey entry;
   unsigned char hash[32];
@@ -529,9 +540,6 @@ bool silc_client_add_channel_private_key(SilcClient client,
 
   assert(client && channel);
 
-  if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
-    return FALSE;
-
   if (!cipher)
     cipher = SILC_DEFAULT_CIPHER;
   if (!hmac)
@@ -550,20 +558,6 @@ bool silc_client_add_channel_private_key(SilcClient client,
       != SILC_SKE_STATUS_OK)
     return FALSE;
 
-  /* Remove the current key, if it exists. */
-  if (channel->channel_key) {
-    silc_cipher_free(channel->channel_key);
-    memset(channel->key, 0, channel->key_len / 8);
-    silc_free(channel->key);
-    channel->channel_key = NULL;
-    channel->key = NULL;
-    channel->key_len = 0;
-  }
-  if (channel->hmac) {
-    silc_hmac_free(channel->hmac);
-    channel->hmac = NULL;
-  }
-
   if (!channel->private_keys)
     channel->private_keys = silc_dlist_init();
 
@@ -594,6 +588,9 @@ bool silc_client_add_channel_private_key(SilcClient client,
   /* Free the key material */
   silc_ske_free_key_material(keymat);
 
+  if (ret_key)
+    *ret_key = entry;
+
   return TRUE;
 }
 
index ed9ca3bcd2a4ae5839507cb96ec93afe5ccfa77f..3e71b5ab07eb55ee11754aacfc84fddd5adb1a3e 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  client_ftp.c 
+  client_ftp.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #include "client_internal.h"
 
 static int
-silc_client_connect_to_client(SilcClient client, 
+silc_client_connect_to_client(SilcClient client,
                              SilcClientConnection conn, int port,
                              char *host, void *context);
-static int 
+static int
 silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx);
 SILC_TASK_CALLBACK(silc_client_ftp_connected);
 static void silc_client_ftp_start_key_agreement(SilcClientFtpSession session,
@@ -48,12 +48,14 @@ struct SilcClientFtpSessionStruct {
 
   SilcClientFileMonitor monitor;
   void *monitor_context;
+  SilcClientFileAskName ask_name;
+  void *ask_name_context;
   char *filepath;
   char *path;
 
   SilcSFTP sftp;
   SilcSFTPFilesystem fs;
-  unsigned int server : 1;
+  unsigned int server : 1;     /* File sender sets this to TRUE */
   unsigned int bound  : 1;
 
   SilcSFTPHandle dir_handle;
@@ -82,8 +84,8 @@ SILC_TASK_CALLBACK(silc_client_ftp_connected)
       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
                                 "Could not connect to client %s: %s",
                                 ctx->host, strerror(opt));
-      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
-                                "Connecting to port %d of client %s resumed", 
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
+                                "Connecting to port %d of client %s resumed",
                                 ctx->port, ctx->host);
 
       /* Unregister old connection try */
@@ -115,7 +117,7 @@ SILC_TASK_CALLBACK(silc_client_ftp_connected)
   silc_client_ftp_start_key_agreement(session, fd);
 }
 
-static int 
+static int
 silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
 {
   int sock;
@@ -127,9 +129,9 @@ silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
 
   /* Register task that will receive the async connect and will
      read the result. */
-  ctx->task = silc_schedule_task_add(ctx->client->schedule, sock, 
+  ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
                                     silc_client_ftp_connected,
-                                    (void *)ctx, 0, 0, 
+                                    (void *)ctx, 0, 0,
                                     SILC_TASK_FD,
                                     SILC_TASK_PRI_NORMAL);
   silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
@@ -139,7 +141,7 @@ silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
 }
 
 static int
-silc_client_connect_to_client(SilcClient client, 
+silc_client_connect_to_client(SilcClient client,
                              SilcClientConnection conn, int port,
                              char *host, void *context)
 {
@@ -185,8 +187,8 @@ static void silc_client_ftp_send_packet(SilcBuffer packet, void *context)
                     SILC_STR_END);
 
   /* Send the packet immediately */
-  silc_client_packet_send(client, session->sock, SILC_PACKET_FTP, NULL, 
-                         0, NULL, NULL, session->packet->data, 
+  silc_client_packet_send(client, session->sock, SILC_PACKET_FTP, NULL,
+                         0, NULL, NULL, session->packet->data,
                          session->packet->len, TRUE);
 
   /* Clear buffer */
@@ -194,7 +196,7 @@ static void silc_client_ftp_send_packet(SilcBuffer packet, void *context)
   session->packet->len = 0;
 }
 
-/* SFTP monitor callback for SFTP server. This reports the application 
+/* SFTP monitor callback for SFTP server. This reports the application
    how the transmission is going along. This function is for the client
    who made the file available for download. */
 
@@ -248,7 +250,7 @@ static void silc_client_ftp_data(SilcSFTP sftp,
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          (status == SILC_SFTP_STATUS_NO_SUCH_FILE ?
                           SILC_CLIENT_FILE_NO_SUCH_FILE :
                           status == SILC_SFTP_STATUS_PERMISSION_DENIED ?
@@ -268,7 +270,7 @@ static void silc_client_ftp_data(SilcSFTP sftp,
 
   /* Read more, until EOF is received */
   session->read_offset += data_len;
-  silc_sftp_read(sftp, session->read_handle, session->read_offset, 
+  silc_sftp_read(sftp, session->read_handle, session->read_offset,
                  SILC_PACKET_MAX_LEN - 1024,
                 silc_client_ftp_data, session);
 
@@ -302,7 +304,7 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          (status == SILC_SFTP_STATUS_NO_SUCH_FILE ?
                           SILC_CLIENT_FILE_NO_SUCH_FILE :
                           status == SILC_SFTP_STATUS_PERMISSION_DENIED ?
@@ -320,16 +322,16 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
   session->fd = silc_file_open(path, O_RDWR | O_CREAT | O_EXCL);
   if (session->fd < 0) {
     /* Call monitor callback */
-    session->client->internal->ops->say(session->client, session->conn, 
-                                       SILC_CLIENT_MESSAGE_ERROR, 
-                                       "File `%s' open failed: %s", 
+    session->client->internal->ops->say(session->client, session->conn,
+                                       SILC_CLIENT_MESSAGE_ERROR,
+                                       "File `%s' open failed: %s",
                                        session->filepath,
                                        strerror(errno));
 
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
-                         SILC_CLIENT_FILE_ERROR, 0, 0,
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
+                         SILC_CLIENT_FILE_PERMISSION_DENIED, 0, 0,
                          session->client_entry, session->session_id,
                          session->filepath, session->monitor_context);
     return;
@@ -352,6 +354,37 @@ static void silc_client_ftp_open_handle(SilcSFTP sftp,
                        session->filepath, session->monitor_context);
 }
 
+static void silc_client_ftp_ask_name(const char *filepath,
+                                    void *context)
+{
+  SilcClientFtpSession session = (SilcClientFtpSession)context;
+  SilcSFTPAttributesStruct attr;
+  char *remote_file = NULL;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (filepath) {
+    remote_file = session->filepath;
+    session->filepath = NULL;
+    silc_free(session->path);
+    session->path = NULL;
+    session->filepath = strdup(filepath);
+  } else {
+    remote_file = strdup(session->filepath);
+  }
+
+  /* Now open the file */
+  memset(&attr, 0, sizeof(attr));
+  silc_sftp_open(session->sftp, remote_file, SILC_SFTP_FXF_READ, &attr,
+                silc_client_ftp_open_handle, session);
+
+  /* Close the directory handle */
+  silc_sftp_close(session->sftp, session->dir_handle, NULL, NULL);
+  session->dir_handle = NULL;
+
+  silc_free(remote_file);
+}
+
 /* Returns the file name available for download. This is the downloader's
    function. */
 
@@ -361,7 +394,6 @@ static void silc_client_ftp_readdir_name(SilcSFTP sftp,
                                         void *context)
 {
   SilcClientFtpSession session = (SilcClientFtpSession)context;
-  SilcSFTPAttributesStruct attr;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -369,7 +401,7 @@ static void silc_client_ftp_readdir_name(SilcSFTP sftp,
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          (status == SILC_SFTP_STATUS_NO_SUCH_FILE ?
                           SILC_CLIENT_FILE_NO_SUCH_FILE :
                           status == SILC_SFTP_STATUS_PERMISSION_DENIED ?
@@ -380,18 +412,21 @@ static void silc_client_ftp_readdir_name(SilcSFTP sftp,
     return;
   }
 
-  /* Now open the file */
-  memset(&attr, 0, sizeof(attr));
-  silc_sftp_open(sftp, name->filename[0], SILC_SFTP_FXF_READ, &attr,
-                silc_client_ftp_open_handle, session);
-
   /* Save the important attributes like filename and file size */
   session->filepath = strdup(name->filename[0]);
   session->filesize = name->attrs[0]->size;
 
-  /* Close the directory handle */
-  silc_sftp_close(sftp, session->dir_handle, NULL, NULL);
-  session->dir_handle = NULL;
+  /* If the path was not provided, ask from application where to save the
+     downloaded file. */
+  if (!session->path && session->ask_name) {
+    session->ask_name(session->client, session->conn, session->session_id,
+                     name->filename[0], silc_client_ftp_ask_name, session,
+                     session->ask_name_context);
+    return;
+  }
+
+  /* Start downloading immediately to current directory. */
+  silc_client_ftp_ask_name(NULL, session);
 }
 
 /* Returns the file handle after giving opendir command. This is the
@@ -410,7 +445,7 @@ static void silc_client_ftp_opendir_handle(SilcSFTP sftp,
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          (status == SILC_SFTP_STATUS_NO_SUCH_FILE ?
                           SILC_CLIENT_FILE_NO_SUCH_FILE :
                           status == SILC_SFTP_STATUS_PERMISSION_DENIED ?
@@ -443,7 +478,7 @@ static void silc_client_ftp_version(SilcSFTP sftp,
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          (status == SILC_SFTP_STATUS_NO_SUCH_FILE ?
                           SILC_CLIENT_FILE_NO_SUCH_FILE :
                           status == SILC_SFTP_STATUS_PERMISSION_DENIED ?
@@ -464,7 +499,7 @@ static void silc_client_ftp_version(SilcSFTP sftp,
 SILC_TASK_CALLBACK(silc_client_ftp_key_agreement_final)
 {
   SilcProtocol protocol = (SilcProtocol)context;
-  SilcClientKEInternalContext *ctx = 
+  SilcClientKEInternalContext *ctx =
     (SilcClientKEInternalContext *)protocol->context;
   SilcClientFtpSession session = (SilcClientFtpSession)ctx->context;
   SilcClientConnection conn = (SilcClientConnection)ctx->sock->user_data;
@@ -476,7 +511,7 @@ SILC_TASK_CALLBACK(silc_client_ftp_key_agreement_final)
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED, 0, 0,
                          session->client_entry, session->session_id,
                          session->filepath, session->monitor_context);
@@ -499,7 +534,7 @@ SILC_TASK_CALLBACK(silc_client_ftp_key_agreement_final)
     /* If we are the SFTP client then start the SFTP session and retrieve
        the info about the file available for download. */
     session->sftp = silc_sftp_client_start(silc_client_ftp_send_packet,
-                                          session, silc_client_ftp_version, 
+                                          session, silc_client_ftp_version,
                                           session);
   } else {
     /* Start SFTP server */
@@ -542,7 +577,7 @@ static void silc_client_ftp_start_key_agreement(SilcClientFtpSession session,
   /* Call monitor callback */
   if (session->monitor)
     (*session->monitor)(session->client, session->conn,
-                       SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT, 
+                       SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT,
                        SILC_CLIENT_FILE_OK, 0, 0,
                        session->client_entry, session->session_id,
                        NULL, session->monitor_context);
@@ -569,15 +604,15 @@ static void silc_client_ftp_start_key_agreement(SilcClientFtpSession session,
   proto_ctx->verify = silc_client_protocol_ke_verify_key;
 
   /* Perform key exchange protocol. */
-  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
+  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
                      &protocol, (void *)proto_ctx,
                      silc_client_ftp_key_agreement_final);
   conn->sock->protocol = protocol;
 
   /* Register the connection for network input and output. This sets
-     that scheduler will listen for incoming packets for this connection 
+     that scheduler will listen for incoming packets for this connection
      and sets that outgoing packets may be sent to this connection as well.
-     However, this doesn't set the scheduler for outgoing traffic, it will 
+     However, this doesn't set the scheduler for outgoing traffic, it will
      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
      later when outgoing data is available. */
   context = (void *)client;
@@ -607,7 +642,7 @@ SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          SILC_CLIENT_FILE_ERROR, 0, 0,
                          session->client_entry, session->session_id,
                          session->filepath, session->monitor_context);
@@ -627,7 +662,7 @@ SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          SILC_CLIENT_FILE_ERROR, 0, 0,
                          session->client_entry, session->session_id,
                          session->filepath, session->monitor_context);
@@ -640,7 +675,7 @@ SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
   /* Call monitor callback */
   if (session->monitor)
     (*session->monitor)(session->client, session->conn,
-                       SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT, 
+                       SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT,
                        SILC_CLIENT_FILE_OK, 0, 0,
                        session->client_entry, session->session_id,
                        NULL, session->monitor_context);
@@ -665,14 +700,14 @@ SILC_TASK_CALLBACK(silc_client_ftp_process_key_agreement)
 
   /* Prepare the connection for key exchange protocol. We allocate the
      protocol but will not start it yet. The connector will be the
-     initiator of the protocol thus we will wait for initiation from 
+     initiator of the protocol thus we will wait for initiation from
      there before we start the protocol. */
-  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
-                     &newsocket->protocol, proto_ctx, 
+  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
+                     &newsocket->protocol, proto_ctx,
                      silc_client_ftp_key_agreement_final);
 
   /* Register the connection for network input and output. This sets
-     that scheduler will listen for incoming packets for this connection 
+     that scheduler will listen for incoming packets for this connection
      and sets that outgoing packets may be sent to this connection as well.
      However, this doesn't set the scheduler for outgoing traffic, it
      will be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
@@ -713,11 +748,8 @@ void silc_client_ftp_session_free_client(SilcClientConnection conn,
   silc_dlist_start(conn->internal->ftp_sessions);
   while ((session = silc_dlist_get(conn->internal->ftp_sessions))
         != SILC_LIST_END) {
-    if (session->client_entry == client_entry) {
-      if (session->sock)
-       session->sock->user_data = NULL;
+    if (session->client_entry == client_entry)
       silc_client_ftp_session_free(session);
-    }
   }
 }
 
@@ -747,7 +779,7 @@ void silc_client_ftp_session_free(SilcClientFtpSession session)
 
   /* Destroy listener */
   if (session->listener) {
-    silc_schedule_unset_listen_fd(session->client->schedule, 
+    silc_schedule_unset_listen_fd(session->client->schedule,
                                  session->listener);
     silc_net_close_connection(session->listener);
     silc_schedule_task_del_by_fd(session->client->schedule, session->listener);
@@ -755,7 +787,7 @@ void silc_client_ftp_session_free(SilcClientFtpSession session)
 
   /* Destroy session connection */
   if (session->sock) {
-    silc_schedule_unset_listen_fd(session->client->schedule, 
+    silc_schedule_unset_listen_fd(session->client->schedule,
                                  session->sock->sock);
     silc_net_close_connection(session->sock->sock);
 
@@ -781,13 +813,13 @@ void silc_client_ftp_session_free(SilcClientFtpSession session)
   silc_free(session);
 }
 
-/* Sends a file indicated by the `filepath' to the remote client 
+/* Sends a file indicated by the `filepath' to the remote client
    indicated by the `client_entry'.  This will negotiate a secret key
    with the remote client before actually starting the transmission of
    the file.  The `monitor' callback will be called to monitor the
    transmission of the file. */
 
-SilcClientFileError 
+SilcClientFileError
 silc_client_file_send(SilcClient client,
                      SilcClientConnection conn,
                      SilcClientFileMonitor monitor,
@@ -812,7 +844,7 @@ silc_client_file_send(SilcClient client,
   silc_dlist_start(conn->internal->ftp_sessions);
   while ((session = silc_dlist_get(conn->internal->ftp_sessions))
         != SILC_LIST_END) {
-    if (session->filepath && !strcmp(session->filepath, filepath) && 
+    if (session->filepath && !strcmp(session->filepath, filepath) &&
        session->client_entry == client_entry)
       return SILC_CLIENT_FILE_ALREADY_STARTED;
   }
@@ -853,17 +885,22 @@ silc_client_file_send(SilcClient client,
 
   /* Create the listener for incoming key exchange protocol. */
   if (!do_not_bind) {
+    session->listener = -1;
     if (local_ip)
       session->hostname = strdup(local_ip);
     else
-      session->hostname = silc_net_localip();
-    session->listener = silc_net_create_server(local_port, session->hostname);
+      silc_net_check_local_by_sock(conn->sock->sock, NULL,
+                                  &session->hostname);
+    if (session->hostname)
+      session->listener = silc_net_create_server(local_port,
+                                                session->hostname);
     if (session->listener < 0) {
       /* Could not create listener. Do the second best thing; send empty
         key agreement packet and let the remote client provide the point
         for the key exchange. */
       SILC_LOG_DEBUG(("Could not create listener"));
       silc_free(session->hostname);
+      session->listener = 0;
       session->hostname = NULL;
       session->port = 0;
     } else {
@@ -909,13 +946,15 @@ silc_client_file_send(SilcClient client,
    actually starting the file transmission.  The `monitor' callback
    will be called to monitor the transmission. */
 
-SilcClientFileError 
+SilcClientFileError
 silc_client_file_receive(SilcClient client,
                         SilcClientConnection conn,
                         SilcClientFileMonitor monitor,
                         void *monitor_context,
                         const char *path,
-                        SilcUInt32 session_id)
+                        SilcUInt32 session_id,
+                        SilcClientFileAskName ask_name,
+                        void *ask_name_context)
 {
   SilcClientFtpSession session;
   SilcBuffer keyagr, ftp;
@@ -946,6 +985,8 @@ silc_client_file_receive(SilcClient client,
 
   session->monitor = monitor;
   session->monitor_context = monitor_context;
+  session->ask_name = ask_name;
+  session->ask_name_context = ask_name_context;
   session->conn = conn;
   session->path = path ? strdup(path) : NULL;
 
@@ -954,18 +995,21 @@ silc_client_file_receive(SilcClient client,
      create the connection ourselves. */
   if (session->hostname && session->port) {
     SILC_LOG_DEBUG(("Connecting to remote client"));
-    if (silc_client_connect_to_client(client, conn, session->port, 
+    if (silc_client_connect_to_client(client, conn, session->port,
                                      session->hostname, session) < 0)
       return SILC_CLIENT_FILE_ERROR;
   } else {
     /* Add the listener for the key agreement */
     SILC_LOG_DEBUG(("Creating listener for file transfer"));
-    session->hostname = silc_net_localip();
-    session->listener = silc_net_create_server(0, session->hostname);
+    session->listener = -1;
+    silc_net_check_local_by_sock(conn->sock->sock, NULL, &session->hostname);
+    if (session->hostname)
+      session->listener = silc_net_create_server(0, session->hostname);
     if (session->listener < 0) {
       SILC_LOG_DEBUG(("Could not create listener"));
-      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR, 
-                                "Cannot create listener on %s: %s", 
+      session->listener = 0;
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                                "Cannot create listener on %s: %s",
                                 session->hostname, strerror(errno));
       return SILC_CLIENT_FILE_ERROR;
     }
@@ -973,10 +1017,10 @@ silc_client_file_receive(SilcClient client,
     silc_schedule_task_add(client->schedule, session->listener,
                           silc_client_ftp_process_key_agreement, session,
                           0, 0, SILC_TASK_FD, SILC_TASK_PRI_NORMAL);
-    
+
     /* Send the key agreement inside FTP packet */
     SILC_LOG_DEBUG(("Sending key agreement for file transfer"));
-    keyagr = silc_key_agreement_payload_encode(session->hostname, 
+    keyagr = silc_key_agreement_payload_encode(session->hostname,
                                               session->port);
     ftp = silc_buffer_alloc(1 + keyagr->len);
     silc_buffer_pull_tail(ftp, SILC_BUFFER_END(ftp));
@@ -985,10 +1029,10 @@ silc_client_file_receive(SilcClient client,
                       SILC_STR_UI_XNSTRING(keyagr->data, keyagr->len),
                       SILC_STR_END);
     silc_client_packet_send(client, conn->sock, SILC_PACKET_FTP,
-                           session->client_entry->id, 
+                           session->client_entry->id,
                            SILC_ID_CLIENT, NULL, NULL,
                            ftp->data, ftp->len, FALSE);
-    
+
     silc_buffer_free(keyagr);
     silc_buffer_free(ftp);
   }
@@ -996,6 +1040,11 @@ silc_client_file_receive(SilcClient client,
   return SILC_CLIENT_FILE_OK;
 }
 
+SILC_TASK_CALLBACK(silc_client_file_close_final)
+{
+  silc_client_ftp_session_free(context);
+}
+
 /* Closes file transmission session indicated by the `session_id'.
    If file transmission is being conducted it will be aborted
    automatically. This function is also used to close the session
@@ -1016,9 +1065,8 @@ SilcClientFileError silc_client_file_close(SilcClient client,
   silc_dlist_start(conn->internal->ftp_sessions);
   while ((session = silc_dlist_get(conn->internal->ftp_sessions))
         != SILC_LIST_END) {
-    if (session->session_id == session_id) {
+    if (session->session_id == session_id)
       break;
-    }
   }
 
   if (session == SILC_LIST_END) {
@@ -1026,7 +1074,17 @@ SilcClientFileError silc_client_file_close(SilcClient client,
     return SILC_CLIENT_FILE_UNKNOWN_SESSION;
   }
 
-  silc_client_ftp_session_free(session);
+  if (session->monitor)
+    (*session->monitor)(session->client, session->conn,
+                       SILC_CLIENT_FILE_MONITOR_CLOSED,
+                       SILC_CLIENT_FILE_OK, 0, 0,
+                       session->client_entry, session->session_id,
+                       session->filepath, session->monitor_context);
+
+  /* Destroy via timeout */
+  silc_schedule_task_add(session->client->schedule, 0,
+                        silc_client_file_close_final, session,
+                        0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 
   return SILC_CLIENT_FILE_OK;
 }
@@ -1077,12 +1135,18 @@ static void silc_client_ftp_resolve_cb(SilcClient client,
   if (!port)
     hostname = NULL;
 
-  if (session == SILC_LIST_END || (!hostname && !port)) {
+  /* If session doesn't exist, we create one and let applicationi know about
+     incoming file transfer request.  If session exists, but we are responder
+     it means that the remote sent another request and user hasn't even
+     accepted the first one yet.  We assume this session is new session
+     as well. */
+  if (session == SILC_LIST_END || (!hostname && !port) ||
+      (session && session->server == FALSE)) {
     /* No session found, create one and let the application know about
        incoming file transfer request. */
     SILC_LOG_DEBUG(("New file transfer session ID: %d",
                    conn->internal->next_session_id + 1));
-    
+
     /* Add new session */
     session = silc_calloc(1, sizeof(*session));
     session->session_id = ++conn->internal->next_session_id;
@@ -1099,22 +1163,23 @@ static void silc_client_ftp_resolve_cb(SilcClient client,
       session->hostname = strdup(hostname);
       session->port = port;
     }
-    
+
     goto out;
   }
 
-  session->hostname = strdup(hostname);
-  session->port = port;
-
   /* Session exists, continue with key agreement protocol. */
   SILC_LOG_DEBUG(("Session ID %d exists, connecting to remote client",
                  session->session_id));
-  if (silc_client_connect_to_client(client, conn, port, 
+
+  session->hostname = strdup(hostname);
+  session->port = port;
+
+  if (silc_client_connect_to_client(client, conn, port,
                                    hostname, session) < 0) {
     /* Call monitor callback */
     if (session->monitor)
       (*session->monitor)(session->client, session->conn,
-                         SILC_CLIENT_FILE_MONITOR_ERROR, 
+                         SILC_CLIENT_FILE_MONITOR_ERROR,
                          SILC_CLIENT_FILE_ERROR, 0, 0,
                          session->client_entry, session->session_id,
                          session->filepath, session->monitor_context);
@@ -1170,7 +1235,7 @@ void silc_client_ftp(SilcClient client,
     if (packet->src_id_type != SILC_ID_CLIENT)
       return;
 
-    remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
+    remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
                               SILC_ID_CLIENT);
     if (!remote_id)
       return;
index 4155d61ed93e77a40f49d779d8f81329e2a96bb8..05b1ff36562571e9ff0d4b9f43a594c60b4b4f23 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001, 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -271,6 +271,9 @@ void silc_client_notify_by_server(SilcClient client,
 void silc_client_private_message(SilcClient client,
                                 SilcSocketConnection sock,
                                 SilcPacketContext *packet);
+void silc_client_private_message_key(SilcClient client,
+                                    SilcSocketConnection sock,
+                                    SilcPacketContext *packet);
 void silc_client_connection_auth_request(SilcClient client,
                                         SilcSocketConnection sock,
                                         SilcPacketContext *packet);
@@ -293,5 +296,9 @@ SilcBuffer silc_client_attributes_process(SilcClient client,
 void silc_client_packet_queue_purge(SilcClient client,
                                    SilcSocketConnection sock);
 SILC_TASK_CALLBACK_GLOBAL(silc_client_rekey_callback);
+void
+silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
+                                    SilcStatus status,
+                                    bool notify);
 
 #endif
index 305c4b4bc7ef3c78ceee420f3f0845e2f7c9b1fb..8027bb3c93b5b0e6a17620b678d14962001bfe36 100644 (file)
@@ -2,15 +2,14 @@
 
   client_keyagr.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -21,7 +20,7 @@
 /* This file includes the Key Agreement packet processing and actual
    key agreement routines. This file has nothing to do with the actual
    connection key exchange protocol, it is implemented in the client.c
-   and in protocol.c. This file implements the client-to-client key 
+   and in protocol.c. This file implements the client-to-client key
    agreement as defined by the SILC protocol. */
 
 #include "silcincludes.h"
@@ -54,7 +53,7 @@ static void silc_client_key_agreement_send_packet(SilcSKE ske,
                                                  void *context)
 {
   SilcProtocol protocol = (SilcProtocol)context;
-  SilcClientKEInternalContext *ctx = 
+  SilcClientKEInternalContext *ctx =
     (SilcClientKEInternalContext *)protocol->context;
   void *tmp;
 
@@ -92,7 +91,7 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_close)
 SILC_TASK_CALLBACK(silc_client_key_agreement_final)
 {
   SilcProtocol protocol = (SilcProtocol)context;
-  SilcClientKEInternalContext *ctx = 
+  SilcClientKEInternalContext *ctx =
     (SilcClientKEInternalContext *)protocol->context;
   SilcClient client = (SilcClient)ctx->client;
   SilcClientKeyAgreement ke = (SilcClientKeyAgreement)ctx->context;
@@ -103,7 +102,7 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_final)
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
     /* Error occured during protocol */
     ke->client_entry->ke = NULL;
-    ke->completion(ke->client, ke->conn, ke->client_entry, 
+    ke->completion(ke->client, ke->conn, ke->client_entry,
                   SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
     silc_ske_free_key_material(ctx->keymat);
     goto out;
@@ -112,7 +111,7 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_final)
   /* Pass the negotiated key material to the application. The application
      is responsible of freeing the key material. */
   ke->client_entry->ke = NULL;
-  ke->completion(ke->client, ke->conn, ke->client_entry, 
+  ke->completion(ke->client, ke->conn, ke->client_entry,
                 SILC_KEY_AGREEMENT_OK, ctx->keymat, ke->context);
 
  out:
@@ -128,9 +127,9 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_final)
     silc_schedule_task_del(client->schedule, ke->timeout);
   silc_client_del_socket(ke->client, ke->sock);
 
-  silc_schedule_task_add(client->schedule, 0, 
+  silc_schedule_task_add(client->schedule, 0,
                     silc_client_key_agreement_close,
-                    (void *)ke, 0, 1, 
+                    (void *)ke, 0, 1,
                     SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 
   silc_free(ctx);
@@ -154,10 +153,10 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
   sock = silc_net_accept_connection(ke->fd);
   if (sock < 0) {
     client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
-                              "Could not accept key agreement connection: ", 
+                              "Could not accept key agreement connection: ",
                               strerror(errno));
     ke->client_entry->ke = NULL;
-    ke->completion(ke->client, ke->conn, ke->client_entry, 
+    ke->completion(ke->client, ke->conn, ke->client_entry,
                   SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
     silc_schedule_task_del_by_fd(client->schedule, ke->fd);
     silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
@@ -181,10 +180,10 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
   /* Perform name and address lookups for the remote host. */
   silc_net_check_host_by_sock(sock, &newsocket->hostname, &newsocket->ip);
   if (!newsocket->hostname && !newsocket->ip) {
-    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
+    client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
                               "Could not resolve the remote IP or hostname");
     ke->client_entry->ke = NULL;
-    ke->completion(ke->client, ke->conn, ke->client_entry, 
+    ke->completion(ke->client, ke->conn, ke->client_entry,
                   SILC_KEY_AGREEMENT_ERROR, NULL, ke->context);
     silc_schedule_task_del_by_fd(client->schedule, ke->fd);
     silc_schedule_unset_listen_fd(ke->client->schedule, ke->fd);
@@ -213,14 +212,14 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
 
   /* Prepare the connection for key exchange protocol. We allocate the
      protocol but will not start it yet. The connector will be the
-     initiator of the protocol thus we will wait for initiation from 
+     initiator of the protocol thus we will wait for initiation from
      there before we start the protocol. */
-  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
-                     &newsocket->protocol, proto_ctx, 
+  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
+                     &newsocket->protocol, proto_ctx,
                      silc_client_key_agreement_final);
 
   /* Register the connection for network input and output. This sets
-     that scheduler will listen for incoming packets for this connection 
+     that scheduler will listen for incoming packets for this connection
      and sets that outgoing packets may be sent to this connection as well.
      However, this doesn't set the scheduler for outgoing traffic, it
      will be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
@@ -230,7 +229,7 @@ SILC_TASK_CALLBACK(silc_client_process_key_agreement)
 }
 
 /* Timeout occured during key agreement. This means that the key agreement
-   protocol was not completed in the specified timeout. We will call the 
+   protocol was not completed in the specified timeout. We will call the
    completion callback. */
 
 SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
@@ -238,7 +237,7 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
   SilcClientKeyAgreement ke = (SilcClientKeyAgreement)context;
 
   ke->client_entry->ke = NULL;
-  ke->completion(ke->client, ke->conn, ke->client_entry, 
+  ke->completion(ke->client, ke->conn, ke->client_entry,
                 SILC_KEY_AGREEMENT_TIMEOUT, NULL, ke->context);
 
   if (ke->sock) {
@@ -269,9 +268,9 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
    the same packet including its hostname and port. If the library receives
    the reply from the remote client the `key_agreement' client operation
    callback will be called to verify whether the user wants to perform the
-   key agreement or not. 
+   key agreement or not.
 
-   NOTE: If the application provided the `hostname' and the `port' and the 
+   NOTE: If the application provided the `hostname' and the `port' and the
    remote side initiates the key agreement protocol it is not verified
    from the user anymore whether the protocol should be executed or not.
    By setting the `hostname' and `port' the user gives permission to
@@ -282,7 +281,7 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
    perform the key agreement at all. If the key agreement protocol is
    performed the `completion' callback with the `context' will be called.
    If remote side decides to ignore the request the `completion' will be
-   called after the specified timeout, `timeout_secs'. 
+   called after the specified timeout, `timeout_secs'.
 
    NOTE: If the `hostname' and the `port' was not provided the `completion'
    will not be called at all since this does nothing more than sending
@@ -290,7 +289,7 @@ SILC_TASK_CALLBACK(silc_client_key_agreement_timeout)
 
    NOTE: There can be only one active key agreement for one client entry.
    Before setting new one, the old one must be finished (it is finished
-   after calling the completion callback) or the function 
+   after calling the completion callback) or the function
    silc_client_abort_key_agreement must be called. */
 
 void silc_client_send_key_agreement(SilcClient client,
@@ -325,10 +324,10 @@ void silc_client_send_key_agreement(SilcClient client,
   /* Create the listener if hostname and port was provided.
    * also, use bindhost if it was specified.
    */
-   
+
   if (hostname) {
     ke = silc_calloc(1, sizeof(*ke));
-    
+
     if (bindhost)
       ke->fd = silc_net_create_server(port, bindhost);
     else
@@ -336,8 +335,8 @@ void silc_client_send_key_agreement(SilcClient client,
 
     if (ke->fd < 0) {
       client->internal->ops->say(
-                    client, conn, SILC_CLIENT_MESSAGE_ERROR, 
-                    "Cannot create listener on %s on port %d: %s", 
+                    client, conn, SILC_CLIENT_MESSAGE_ERROR,
+                    "Cannot create listener on %s on port %d: %s",
                     (bindhost) ? bindhost:hostname, port, strerror(errno));
       completion(client, conn, client_entry, SILC_KEY_AGREEMENT_FAILURE,
                 NULL, context);
@@ -351,26 +350,26 @@ void silc_client_send_key_agreement(SilcClient client,
     ke->completion = completion;
     ke->context = context;
 
-    /* Add listener task to the scheduler. This task receives the key 
+    /* Add listener task to the scheduler. This task receives the key
        negotiations. */
     silc_schedule_task_add(client->schedule, ke->fd,
                           silc_client_process_key_agreement,
-                          (void *)ke, 0, 0, 
+                          (void *)ke, 0, 0,
                           SILC_TASK_FD,
                           SILC_TASK_PRI_NORMAL);
 
     /* Register a timeout task that will be executed if the connector
-       will not start the key exchange protocol within the specified 
+       will not start the key exchange protocol within the specified
        timeout. */
-    ke->timeout = silc_schedule_task_add(client->schedule, 0, 
+    ke->timeout = silc_schedule_task_add(client->schedule, 0,
                                         silc_client_key_agreement_timeout,
-                                        (void *)ke, timeout_secs, 0, 
+                                        (void *)ke, timeout_secs, 0,
                                         SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
   }
 
   /* Encode the key agreement payload */
-  buffer = silc_key_agreement_payload_encode(hostname, 
-                                            !ke ? port : 
+  buffer = silc_key_agreement_payload_encode(hostname,
+                                            !ke ? port :
                                             silc_net_get_local_port(ke->fd));
 
   /* Send the key agreement packet to the client */
@@ -380,7 +379,7 @@ void silc_client_send_key_agreement(SilcClient client,
   silc_buffer_free(buffer);
 }
 
-static int 
+static int
 silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
 {
   int sock;
@@ -392,9 +391,9 @@ silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
 
   /* Register task that will receive the async connect and will
      read the result. */
-  ctx->task = silc_schedule_task_add(ctx->client->schedule, sock, 
+  ctx->task = silc_schedule_task_add(ctx->client->schedule, sock,
                                     silc_client_perform_key_agreement_start,
-                                    (void *)ctx, 0, 0, 
+                                    (void *)ctx, 0, 0,
                                     SILC_TASK_FD,
                                     SILC_TASK_PRI_NORMAL);
   silc_schedule_set_listen_fd(ctx->client->schedule, sock, SILC_TASK_WRITE,
@@ -409,7 +408,7 @@ silc_client_connect_to_client_internal(SilcClientInternalConnectContext *ctx)
    to the remote client on specified port. */
 
 static int
-silc_client_connect_to_client(SilcClient client, 
+silc_client_connect_to_client(SilcClient client,
                              SilcClientConnection conn, int port,
                              char *host, void *context)
 {
@@ -451,8 +450,8 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
       client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_ERROR,
                                 "Could not connect to client %s: %s",
                                 ctx->host, strerror(opt));
-      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
-                                "Connecting to port %d of client %s resumed", 
+      client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_AUDIT,
+                                "Connecting to port %d of client %s resumed",
                                 ctx->port, ctx->host);
 
       /* Unregister old connection try */
@@ -475,7 +474,7 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
       silc_free(ctx);
 
       /* Call the completion callback */
-      ke->completion(ke->client, ke->conn, ke->client_entry, 
+      ke->completion(ke->client, ke->conn, ke->client_entry,
                     SILC_KEY_AGREEMENT_FAILURE, NULL, ke->context);
       silc_free(ke);
     }
@@ -504,7 +503,7 @@ SILC_TASK_CALLBACK(silc_client_perform_key_agreement_start)
    The `hostname' is the remote hostname (or IP address) and the `port'
    is the remote port. The `completion' callback with the `context' will
    be called after the key agreement protocol.
-   
+
    NOTE: If the application returns TRUE in the `key_agreement' client
    operation the library will automatically start the key agreement. In this
    case the application must not call this function. However, application
@@ -560,8 +559,8 @@ void silc_client_perform_key_agreement(SilcClient client,
   }
 }
 
-/* Same as above but application has created already the connection to 
-   the remote host. The `sock' is the socket to the remote connection. 
+/* Same as above but application has created already the connection to
+   the remote host. The `sock' is the socket to the remote connection.
    Application can use this function if it does not want the client library
    to create the connection. */
 
@@ -615,15 +614,15 @@ void silc_client_perform_key_agreement_fd(SilcClient client,
   ke->proto_ctx = proto_ctx;
 
   /* Perform key exchange protocol. */
-  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE, 
+  silc_protocol_alloc(SILC_PROTOCOL_CLIENT_KEY_EXCHANGE,
                      &protocol, (void *)proto_ctx,
                      silc_client_key_agreement_final);
   ke->sock->protocol = protocol;
 
   /* Register the connection for network input and output. This sets
-     that scheduler will listen for incoming packets for this connection 
+     that scheduler will listen for incoming packets for this connection
      and sets that outgoing packets may be sent to this connection as well.
-     However, this doesn't set the scheduler for outgoing traffic, it will 
+     However, this doesn't set the scheduler for outgoing traffic, it will
      be set separately by calling SILC_CLIENT_SET_CONNECTION_FOR_OUTPUT,
      later when outgoing data is available. */
   context = (void *)client;
@@ -634,10 +633,10 @@ void silc_client_perform_key_agreement_fd(SilcClient client,
 }
 
 /* This function can be called to unbind the hostname and the port for
-   the key agreement protocol. However, this function has effect only 
+   the key agreement protocol. However, this function has effect only
    before the key agreement protocol has been performed. After it has
-   been performed the library will automatically unbind the port. The 
-   `client_entry' is the client to which we sent the key agreement 
+   been performed the library will automatically unbind the port. The
+   `client_entry' is the client to which we sent the key agreement
    request. */
 
 void silc_client_abort_key_agreement(SilcClient client,
@@ -656,21 +655,21 @@ void silc_client_abort_key_agreement(SilcClient client,
     }
     silc_schedule_task_del_by_fd(client->schedule, client_entry->ke->fd);
     if (client_entry->ke->timeout)
-      silc_schedule_task_del(client->schedule, 
+      silc_schedule_task_del(client->schedule,
                             client_entry->ke->timeout);
     ke = client_entry->ke;
     client_entry->ke = NULL;
-    ke->completion(client, conn, client_entry, 
+    ke->completion(client, conn, client_entry,
                   SILC_KEY_AGREEMENT_ABORTED, NULL, ke->context);
     silc_free(ke);
   }
 }
 
-/* Callback function that is called after we've resolved the client 
+/* Callback function that is called after we've resolved the client
    information who sent us the key agreement packet from the server.
    We actually call the key_agreement client operation now. */
 
-static void 
+static void
 silc_client_key_agreement_resolve_cb(SilcClient client,
                                     SilcClientConnection conn,
                                     SilcClientEntry *clients,
@@ -694,7 +693,7 @@ silc_client_key_agreement_resolve_cb(SilcClient client,
 
   /* Call the key_agreement client operation */
   ret = client->internal->ops->key_agreement(
-                                  client, conn, clients[0], 
+                                  client, conn, clients[0],
                                   silc_key_agreement_get_hostname(payload),
                                   silc_key_agreement_get_port(payload),
                                   &completion, &completion_context);
@@ -715,7 +714,7 @@ silc_client_key_agreement_resolve_cb(SilcClient client,
 
 /* Received Key Agreement packet from remote client. Process the packet
    and resolve the client information from the server before actually
-   letting the application know that we've received this packet.  Then 
+   letting the application know that we've received this packet.  Then
    call the key_agreement client operation and let the user decide
    whether we perform the key agreement protocol now or not. */
 
@@ -728,7 +727,7 @@ void silc_client_key_agreement(SilcClient client,
   if (packet->src_id_type != SILC_ID_CLIENT)
     return;
 
-  remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
+  remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
                             SILC_ID_CLIENT);
   if (!remote_id)
     return;
index b5387ef345cc9b4befeb792eb3edce620bcf1491..eb1f97edb9d95bcb1bae370c21cbeba5946468a0 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -444,12 +444,6 @@ void silc_client_notify_by_server(SilcClient client,
     if (!client_entry)
       goto out;
 
-    /* Remove from all channels */
-    silc_client_remove_from_channels(client, conn, client_entry);
-
-    /* Remove from cache */
-    silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
-
     /* Get signoff message */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
     if (tmp_len > 128)
@@ -458,6 +452,12 @@ void silc_client_notify_by_server(SilcClient client,
     /* Notify application */
     client->internal->ops->notify(client, conn, type, client_entry, tmp);
 
+    /* Remove from all channels */
+    silc_client_remove_from_channels(client, conn, client_entry);
+
+    /* Remove from cache */
+    silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
+
     /* Free data */
     silc_client_del_client_entry(client, conn, client_entry);
     break;
@@ -556,6 +556,11 @@ void silc_client_notify_by_server(SilcClient client,
       goto out;
     }
 
+    if (tmp) {
+      silc_free(channel->topic);
+      channel->topic = silc_memdup(tmp, strlen(tmp));
+    }
+
     /* Notify application. The channel entry is sent last as this notify
        is for channel but application don't know it from the arguments
        sent by server. */
@@ -627,13 +632,20 @@ void silc_client_notify_by_server(SilcClient client,
        ID changes.  Check whether the hashes in the Client ID match, if
        they do nickname didn't change. */
     if (SILC_ID_COMPARE_HASH(client_entry->id, client_id) &&
-       !strcmp(tmp, client_entry->nickname)) {
+       silc_utf8_strcasecmp(tmp, client_entry->nickname)) {
       /* Nickname didn't change.  Update only Client ID. */
+
+      /* Normalize nickname */
+      tmp = silc_identifier_check(tmp, strlen(tmp),
+                                 SILC_STRING_UTF8, 128, NULL);
+      if (!tmp)
+       goto out;
+
       silc_idcache_del_by_context(conn->internal->client_cache,
                                  client_entry);
       silc_free(client_entry->id);
       client_entry->id = silc_id_dup(client_id, SILC_ID_CLIENT);
-      silc_idcache_add(conn->internal->client_cache, strdup(tmp),
+      silc_idcache_add(conn->internal->client_cache, tmp,
                       client_entry->id, client_entry, 0, NULL);
 
       /* Notify application */
@@ -839,6 +851,13 @@ void silc_client_notify_by_server(SilcClient client,
          founder_key = NULL;
       }
 
+      /* Get user limit */
+      tmp = silc_argument_get_arg_type(args, 8, &tmp_len);
+      if (tmp && tmp_len == 4)
+        SILC_GET32_MSB(channel->user_limit, tmp);
+      if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT))
+        channel->user_limit = 0;
+
       /* Get the channel public key that was added or removed */
       tmp = silc_argument_get_arg_type(args, 7, &tmp_len);
       if (tmp)
@@ -1118,26 +1137,29 @@ void silc_client_notify_by_server(SilcClient client,
     /* Get comment */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
 
+    /* Remove kicked client from channel */
+    if (client_entry != conn->local_entry) {
+      chu = silc_client_on_channel(channel, client_entry);
+      if (chu) {
+       silc_hash_table_del(client_entry->channels, channel);
+       silc_hash_table_del(channel->user_list, client_entry);
+       silc_free(chu);
+      }
+    }
+
     /* Notify application. The channel entry is sent last as this notify
        is for channel but application don't know it from the arguments
        sent by server. */
     client->internal->ops->notify(client, conn, type, client_entry, tmp,
                                  client_entry2, channel);
 
-    /* Remove kicked client from channel */
+    /* Remove kicked client (us) from channel */
     if (client_entry == conn->local_entry) {
       /* If I was kicked from channel, remove the channel */
       if (conn->current_channel == channel)
        conn->current_channel = NULL;
       silc_client_del_channel(client, conn, channel);
     } else {
-      chu = silc_client_on_channel(channel, client_entry);
-      if (chu) {
-       silc_hash_table_del(client_entry->channels, channel);
-       silc_hash_table_del(channel->user_list, client_entry);
-       silc_free(chu);
-      }
-
       if (!silc_hash_table_count(client_entry->channels)) {
        SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
        res->context = client;
@@ -1348,6 +1370,9 @@ void silc_client_notify_by_server(SilcClient client,
        */
       SilcNotifyType notify = 0;
       bool del_client = FALSE;
+      unsigned char *pk;
+      SilcUInt32 pk_len;
+      SilcPublicKey public_key = NULL;
 
       SILC_LOG_DEBUG(("Notify: WATCH"));
 
@@ -1393,15 +1418,25 @@ void silc_client_notify_by_server(SilcClient client,
 
        /* If same nick, the client was new to us and has become "present"
           to network.  Send NULL as nick to application. */
-       if (tmp_nick && !strcmp(tmp, tmp_nick))
+       if (tmp_nick && silc_utf8_strcasecmp(tmp, tmp_nick))
          tmp = NULL;
 
        silc_free(tmp_nick);
       }
 
+      /* Get public key, if present */
+      pk = silc_argument_get_arg_type(args, 5, &pk_len);
+      if (pk && !client_entry->public_key) {
+        if (silc_pkcs_public_key_payload_decode(pk, pk_len, &public_key)) {
+         client_entry->public_key = public_key;
+         public_key = NULL;
+       }
+      }
+
       /* Notify application. */
       client->internal->ops->notify(client, conn, type, client_entry,
-                                   tmp, mode, notify);
+                                   tmp, mode, notify,
+                                   client_entry->public_key);
 
       client_entry->mode = mode;
 
@@ -1425,6 +1460,8 @@ void silc_client_notify_by_server(SilcClient client,
                               silc_client_notify_del_client_cb, res,
                               1, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
       }
+
+      silc_pkcs_public_key_free(public_key);
     }
     break;
 
index 19b9acc14fdc856291da82e83f43c54b5f13938e..4fe166a873b54004f30519bb3ffd58b1dfd550ce 100644 (file)
@@ -31,15 +31,16 @@ silc_say(SilcClient client, SilcClientConnection conn,
 static void
 silc_channel_message(SilcClient client, SilcClientConnection conn,
                     SilcClientEntry sender, SilcChannelEntry channel,
-                    SilcMessagePayload payload, SilcMessageFlags flags,
-                    const unsigned char *message, SilcUInt32 message_len)
+                    SilcMessagePayload payload, SilcChannelPrivateKey key,
+                    SilcMessageFlags flags, const unsigned char *message,
+                    SilcUInt32 message_len)
 {
 
 }
 
 
 /* Private message to the client. The `sender' is the sender of the
-   message. The message is `message'and maybe NULL.  The `flags'  
+   message. The message is `message'and maybe NULL.  The `flags'
    indicates message flags  and it is used to determine how the message
    can be interpreted (like it may tell the message is multimedia
    message). */
index d0b72c97ccda970a3aaa20306794a02b99c0afb5..fbd5655e0e6416c9a2bb6797f1657a4b1f5c46cf 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  client_prvmsg.c 
+  client_prvmsg.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -36,8 +36,8 @@ bool silc_client_send_private_message(SilcClient client,
                                      SilcClientConnection conn,
                                      SilcClientEntry client_entry,
                                      SilcMessageFlags flags,
-                                     unsigned char *data, 
-                                     SilcUInt32 data_len, 
+                                     unsigned char *data,
+                                     SilcUInt32 data_len,
                                      bool force_send)
 {
   SilcSocketConnection sock;
@@ -74,6 +74,7 @@ bool silc_client_send_private_message(SilcClient client,
     silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE,
                            client_entry->id, SILC_ID_CLIENT, NULL, NULL,
                            buffer->data, buffer->len, force_send);
+    ret = TRUE;
     goto out;
   }
 
@@ -98,14 +99,14 @@ bool silc_client_send_private_message(SilcClient client,
   data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
                                 packetdata.src_id_len +
                                 packetdata.dst_id_len);
-  packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
+  packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN +
     packetdata.src_id_len + packetdata.dst_id_len;
   SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
                      packetdata.src_id_len +
                      packetdata.dst_id_len), block_len, packetdata.padlen);
 
   /* Create the outgoing packet */
-  if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock, 
+  if (!silc_packet_assemble(&packetdata, client->rng, cipher, hmac, sock,
                             data, data_len, (const SilcBuffer)&packet)) {
     SILC_LOG_ERROR(("Error assembling packet"));
     goto out;
@@ -137,7 +138,7 @@ bool silc_client_send_private_message(SilcClient client,
   silc_buffer_free(buffer);
 
   return ret;
-}     
+}
 
 static void silc_client_private_message_cb(SilcClient client,
                                           SilcClientConnection conn,
@@ -159,8 +160,8 @@ static void silc_client_private_message_cb(SilcClient client,
 /* Private message received. This processes the private message and
    finally displays it on the screen. */
 
-void silc_client_private_message(SilcClient client, 
-                                SilcSocketConnection sock, 
+void silc_client_private_message(SilcClient client,
+                                SilcSocketConnection sock,
                                 SilcPacketContext *packet)
 {
   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
@@ -176,7 +177,7 @@ void silc_client_private_message(SilcClient client,
   if (packet->src_id_type != SILC_ID_CLIENT)
     goto out;
 
-  remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
+  remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
                             SILC_ID_CLIENT);
   if (!remote_id)
     goto out;
@@ -275,22 +276,8 @@ static void silc_client_private_message_key_cb(SilcClient client,
   if (key_len > packet->buffer->len)
     goto out;
 
-  /* Now take the key in use */
-  if (!silc_client_add_private_message_key(client, conn, clients[0],
-                                          cipher, hmac, key, key_len,
-                                          FALSE, TRUE))
-    goto out;
-
-  /* Print some info for application */
-  client->internal->ops->say(
-                    client, conn, SILC_CLIENT_MESSAGE_AUDIT, 
-                    "Received private message key from %s%s%s %s%s%s", 
-                    clients[0]->nickname,
-                    clients[0]->server ? "@" : "",
-                    clients[0]->server ? clients[0]->server : "",
-                    clients[0]->username ? "(" : "",
-                    clients[0]->username ? clients[0]->username : "",
-                    clients[0]->username ? ")" : "");
+  /* Mark that we are responder */
+  clients[0]->prv_resp = TRUE;
 
  out:
   silc_free(cipher);
@@ -298,8 +285,8 @@ static void silc_client_private_message_key_cb(SilcClient client,
   silc_packet_context_free(packet);
 }
 
-/* Processes incoming Private Message Key payload. The libary always
-   accepts the key and takes it into use. */
+/* Processes incoming Private Message Key payload to indicate that the
+   sender whishes to set up a static private message key. */
 
 void silc_client_private_message_key(SilcClient client,
                                     SilcSocketConnection sock,
@@ -310,7 +297,7 @@ void silc_client_private_message_key(SilcClient client,
   if (packet->src_id_type != SILC_ID_CLIENT)
     return;
 
-  remote_id = silc_id_str2id(packet->src_id, packet->src_id_len, 
+  remote_id = silc_id_str2id(packet->src_id, packet->src_id_len,
                             SILC_ID_CLIENT);
   if (!remote_id)
     return;
@@ -338,7 +325,7 @@ void silc_client_private_message_key(SilcClient client,
 
    It is not necessary to set key for normal private message usage. If the
    key is not set then the private messages are encrypted using normal
-   session keys. Setting the private key, however, increases the security. 
+   session keys. Setting the private key, however, increases the security.
 
    Returns FALSE if the key is already set for the `client_entry', TRUE
    otherwise. */
@@ -391,8 +378,8 @@ bool silc_client_add_private_message_key(SilcClient client,
 
   /* Produce the key material as the protocol defines */
   keymat = silc_calloc(1, sizeof(*keymat));
-  if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
-                                        client->sha1hash, keymat) 
+  if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16,
+                                        client->sha1hash, keymat)
       != SILC_SKE_STATUS_OK)
     return FALSE;
 
@@ -500,20 +487,13 @@ bool silc_client_add_private_message_key_ske(SilcClient client,
   return TRUE;
 }
 
-/* Sends private message key payload to the remote client indicated by
-   the `client_entry'. If the `force_send' is TRUE the packet is sent
-   immediately. Returns FALSE if error occurs, TRUE otherwise. The
-   application should call this function after setting the key to the
-   client.
+/* Sends private message key indicator.  The sender of this packet is
+   going to be the initiator, if and when, the users set up a static
+   private message key (not Key Agreement). */
 
-   Note that the key sent using this function is sent to the remote client
-   through the SILC network. The packet is protected using normal session
-   keys. */
-
-bool silc_client_send_private_message_key(SilcClient client,
-                                        SilcClientConnection conn,
-                                        SilcClientEntry client_entry,
-                                        bool force_send)
+bool silc_client_send_private_message_key_request(SilcClient client,
+                                                 SilcClientConnection conn,
+                                                 SilcClientEntry client_entry)
 {
   SilcSocketConnection sock;
   SilcBuffer buffer;
@@ -526,7 +506,7 @@ bool silc_client_send_private_message_key(SilcClient client,
   if (!client_entry->send_key || !client_entry->key)
     return FALSE;
 
-  SILC_LOG_DEBUG(("Sending private message key"));
+  SILC_LOG_DEBUG(("Sending private message key indicator"));
 
   cipher = silc_cipher_get_name(client_entry->send_key);
   cipher_len = strlen(cipher);
@@ -534,12 +514,8 @@ bool silc_client_send_private_message_key(SilcClient client,
   hmac_len = strlen(hmac);
 
   /* Create private message key payload */
-  buffer = silc_buffer_alloc(2 + client_entry->key_len);
-  silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
+  buffer = silc_buffer_alloc_size(4 + cipher_len + hmac_len);
   silc_buffer_format(buffer,
-                    SILC_STR_UI_SHORT(client_entry->key_len),
-                    SILC_STR_UI_XNSTRING(client_entry->key, 
-                                         client_entry->key_len),
                     SILC_STR_UI_SHORT(cipher_len),
                     SILC_STR_UI_XNSTRING(cipher,
                                          cipher_len),
@@ -551,7 +527,7 @@ bool silc_client_send_private_message_key(SilcClient client,
   /* Send the packet */
   silc_client_packet_send(client, sock, SILC_PACKET_PRIVATE_MESSAGE_KEY,
                          client_entry->id, SILC_ID_CLIENT, NULL, NULL,
-                         buffer->data, buffer->len, force_send);
+                         buffer->data, buffer->len, TRUE);
   silc_free(buffer);
 
   return TRUE;
@@ -588,7 +564,7 @@ bool silc_client_del_private_message_key(SilcClient client,
 /* Returns array of set private message keys associated to the connection
    `conn'. Returns allocated SilcPrivateMessageKeys array and the array
    count to the `key_count' argument. The array must be freed by the caller
-   by calling the silc_client_free_private_message_keys function. Note: 
+   by calling the silc_client_free_private_message_keys function. Note:
    the keys returned in the array is in raw format. It might not be desired
    to show the keys as is. The application might choose not to show the keys
    at all or to show the fingerprints of the keys. */
@@ -652,7 +628,7 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
    to anyone who sends private message.  The `message' will be sent
    automatically back to the the client who send private message.  If
    away message is already set this replaces the old message with the
-   new one.  If `message' is NULL the old away message is removed. 
+   new one.  If `message' is NULL the old away message is removed.
    The sender may freely free the memory of the `message'. */
 
 void silc_client_set_away_message(SilcClient client,
index 3efe64ad2c2c6b59d6df4685ee27aa1bd7b91cac..928c7df9f4024102800538e064c8841e1ae2c97b 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002, 2003 Pekka Riikonen
+  Copyright (C) 2002, 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -67,7 +67,7 @@ SilcBuffer silc_client_get_detach_data(SilcClient client,
 
   /* Save all joined channels */
   silc_hash_table_list(conn->local_entry->channels, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
     unsigned char *chid = silc_id_id2str(chu->channel->id, SILC_ID_CHANNEL);
     SilcUInt16 chid_len = silc_id_get_len(chu->channel->id, SILC_ID_CHANNEL);
 
@@ -110,18 +110,21 @@ bool silc_client_process_detach_data(SilcClient client,
   SilcBufferStruct detach;
   SilcUInt32 ch_count;
   int i, len;
+  char *newnick;
 
   SILC_LOG_DEBUG(("Start"));
 
-  silc_free(conn->nickname);
   silc_buffer_set(&detach, conn->internal->params.detach_data,
                  conn->internal->params.detach_data_len);
 
   SILC_LOG_HEXDUMP(("Detach data"), detach.data, detach.len);
 
+  *old_id = NULL;
+  *old_id_len = 0;
+
   /* Take the old client ID from the detachment data */
   len = silc_buffer_unformat(&detach,
-                            SILC_STR_UI16_NSTRING_ALLOC(&conn->nickname,
+                            SILC_STR_UI16_NSTRING_ALLOC(&newnick,
                                                         NULL),
                             SILC_STR_UI16_NSTRING_ALLOC(old_id, old_id_len),
                             SILC_STR_UI_INT(NULL),
@@ -129,6 +132,11 @@ bool silc_client_process_detach_data(SilcClient client,
                             SILC_STR_END);
   if (len == -1)
     return FALSE;
+  if (!newnick || !(*old_id) || !(*old_id_len))
+    return FALSE;
+
+  silc_free(conn->nickname);
+  conn->nickname = newnick;
 
   silc_buffer_pull(&detach, len);
 
index 557a539c9c8186daa7d4e62a3c345c43372dd95f..e2537fe69ca3b2a7a5daf0347e83ef4f63895531 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
 
 #define SILC_NOT_CONNECTED(x, c) \
   x->internal->ops->say((x), (c), SILC_CLIENT_MESSAGE_ERROR, \
-          "You are not connected to a server, use /SERVER to connect");
+          "You are not connected to a server, please connect to server");
 
 /* Command operation that is called at the end of all commands.
    Usage: COMMAND(status); */
@@ -285,6 +285,9 @@ SILC_CLIENT_CMD_FUNC(whois)
   SilcClientConnection conn = cmd->conn;
   SilcBuffer buffer, attrs = NULL;
   unsigned char count[4], *tmp = NULL;
+  int i;
+  bool details = FALSE, nick = FALSE;
+  unsigned char *pubkey = NULL;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -302,28 +305,75 @@ SILC_CLIENT_CMD_FUNC(whois)
     goto out;
   }
 
-  if (cmd->argc == 2) {
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS,
-                                           ++conn->cmd_ident, 1,
-                                           1, cmd->argv[1],
-                                           cmd->argv_lens[1]);
-  } else {
-    if (!strcasecmp(cmd->argv[2], "-details"))
+  for (i = 1; i < cmd->argc; i++) {
+    if (!strcasecmp(cmd->argv[i], "-details")) {
+       details = TRUE;
+    } else if (!strcasecmp(cmd->argv[i], "-pubkey") && cmd->argc > i + 1) {
+       pubkey = cmd->argv[i + 1];
+       i++;
+    } else {
+      /* We assume that the first parameter is the nickname, if it isn't
+         -details or -pubkey. The last parameter should always be the count */
+      if (i == 1) {
+       nick = TRUE;
+      } else if (i == cmd->argc - 1) {
+       int c = atoi(cmd->argv[i]);
+       SILC_PUT32_MSB(c, count);
+       tmp = count;
+      }
+    }
+  }
+
+  if (details) {
+    /* if pubkey is set, add all attributes to the
+       attrs buffer, except public key */
+    if (pubkey) {
+      attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
+                                             SILC_ATTRIBUTE_SERVICE,
+                                             SILC_ATTRIBUTE_STATUS_MOOD,
+                                             SILC_ATTRIBUTE_STATUS_FREETEXT,
+                                             SILC_ATTRIBUTE_STATUS_MESSAGE,
+                                             SILC_ATTRIBUTE_PREFERRED_LANGUAGE,
+                                             SILC_ATTRIBUTE_PREFERRED_CONTACT,
+                                             SILC_ATTRIBUTE_TIMEZONE,
+                                             SILC_ATTRIBUTE_GEOLOCATION,
+                                             SILC_ATTRIBUTE_DEVICE_INFO, 0);
+    } else {
       attrs = silc_client_attributes_request(0);
+    }
+  }
 
-    if (!attrs || cmd->argc > 3) {
-      int c = atoi(cmd->argc > 3 ? cmd->argv[3] : cmd->argv[2]);
-      SILC_PUT32_MSB(c, count);
-      tmp = count;
+  if (pubkey) {
+    SilcAttributeObjPk obj;
+    SilcPublicKey pk;
+
+    if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_PEM)) {
+      if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_BIN)) {
+       SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+           "Could not load public key %s, check the filename",
+           pubkey);
+       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+       goto out;
+      }
     }
 
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS,
-                                           ++conn->cmd_ident, 3,
-                                           1, cmd->argv[1], cmd->argv_lens[1],
-                                           2, tmp ? tmp : NULL, tmp ? 4 : 0,
-                                           3, attrs ? attrs->data : NULL,
-                                           attrs ? attrs->len : 0);
+    obj.type = "silc-rsa";
+    obj.data = silc_pkcs_public_key_encode(pk, &obj.data_len);
+
+    attrs = silc_attribute_payload_encode(attrs,
+                                          SILC_ATTRIBUTE_USER_PUBLIC_KEY,
+                                          SILC_ATTRIBUTE_FLAG_VALID,
+                                          &obj, sizeof(obj));
   }
+
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS,
+                                          ++conn->cmd_ident, 3,
+                                          1, nick ? cmd->argv[1] : NULL,
+                                          nick ? cmd->argv_lens[1] : 0,
+                                          2, tmp ? tmp : NULL, tmp ? 4 : 0,
+                                          3, attrs ? attrs->data : NULL,
+                                          attrs ? attrs->len : 0);
+
   silc_client_packet_send(cmd->client, cmd->conn->sock,
                          SILC_PACKET_COMMAND, NULL, 0, NULL, NULL,
                          buffer->data, buffer->len, TRUE);
@@ -455,7 +505,7 @@ SILC_CLIENT_CMD_FUNC(nick)
     goto out;
   }
 
-  if (!strcmp(conn->nickname, cmd->argv[1]))
+  if (silc_utf8_strcasecmp(conn->nickname, cmd->argv[1]))
     goto out;
 
   /* Show current nickname */
@@ -497,10 +547,8 @@ SILC_CLIENT_CMD_FUNC(list)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
-  SilcIDCacheEntry id_cache = NULL;
   SilcChannelEntry channel;
   SilcBuffer buffer, idp = NULL;
-  char *name;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -509,14 +557,10 @@ SILC_CLIENT_CMD_FUNC(list)
   }
 
   if (cmd->argc == 2) {
-    name = cmd->argv[1];
-
     /* Get the Channel ID of the channel */
-    if (silc_idcache_find_by_name_one(conn->internal->channel_cache,
-                                     name, &id_cache)) {
-      channel = (SilcChannelEntry)id_cache->context;
-      idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
-    }
+    channel = silc_client_get_channel(cmd->client, cmd->conn, cmd->argv[1]);
+    if (channel)
+      idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
   }
 
   if (!idp)
@@ -547,7 +591,6 @@ SILC_CLIENT_CMD_FUNC(topic)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
-  SilcIDCacheEntry id_cache = NULL;
   SilcChannelEntry channel;
   SilcBuffer buffer, idp;
   char *name;
@@ -582,16 +625,14 @@ SILC_CLIENT_CMD_FUNC(topic)
   }
 
   /* Get the Channel ID of the channel */
-  if (!silc_idcache_find_by_name_one(conn->internal->channel_cache,
-                                    name, &id_cache)) {
+  channel = silc_client_get_channel(cmd->client, conn, name);
+  if (!channel) {
     COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
   }
 
-  channel = (SilcChannelEntry)id_cache->context;
-
   /* Send TOPIC command to the server */
-  idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
+  idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
   if (cmd->argc > 2)
     buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC,
                                            ++conn->cmd_ident, 2,
@@ -747,7 +788,7 @@ SILC_CLIENT_CMD_FUNC(invite)
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
   silc_buffer_free(chidp);
-  silc_buffer_free(args),
+  silc_buffer_free(args);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -790,10 +831,12 @@ SILC_CLIENT_CMD_FUNC(quit)
   if (cmd->argc > 1)
     buffer = silc_command_payload_encode(SILC_COMMAND_QUIT, cmd->argc - 1,
                                         &cmd->argv[1], &cmd->argv_lens[1],
-                                        &cmd->argv_types[1], 0);
+                                        &cmd->argv_types[1],
+                                        ++cmd->conn->cmd_ident);
   else
     buffer = silc_command_payload_encode(SILC_COMMAND_QUIT, 0,
-                                        NULL, NULL, NULL, 0);
+                                        NULL, NULL, NULL,
+                                        ++cmd->conn->cmd_ident);
   silc_client_packet_send(cmd->client, cmd->conn->sock, SILC_PACKET_COMMAND,
                          NULL, 0, NULL, NULL,
                          buffer->data, buffer->len, TRUE);
@@ -982,11 +1025,12 @@ SILC_CLIENT_CMD_FUNC(info)
 
   /* Send the command */
   if (name)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_INFO, 0, 1,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_INFO,
+                                           ++conn->cmd_ident, 1,
                                            1, name, strlen(name));
   else
     buffer = silc_command_payload_encode(SILC_COMMAND_INFO, 0,
-                                        NULL, NULL, NULL, 0);
+                                        NULL, NULL, NULL, ++conn->cmd_ident);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
@@ -1052,7 +1096,8 @@ SILC_CLIENT_CMD_FUNC(ping)
   idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
 
   /* Send the command */
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_PING, 0, 1,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_PING,
+                                         ++conn->cmd_ident, 1,
                                          1, idp->data, idp->len);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
@@ -1142,7 +1187,6 @@ SILC_CLIENT_CMD_FUNC(join)
                                                cmd->client->sha1hash,
                                                conn->local_id,
                                                SILC_ID_CLIENT);
-      i++;
     } else if (!strcasecmp(cmd->argv[i], "-auth")) {
       SilcPublicKey pubkey = cmd->client->public_key;
       SilcPrivateKey privkey = cmd->client->private_key;
@@ -1177,7 +1221,6 @@ SILC_CLIENT_CMD_FUNC(join)
                                                      SILC_ID_CLIENT);
       memset(pubdata, 0, 128);
       silc_free(pubdata);
-      i++;
     } else {
       /* Passphrases must be UTF-8 encoded, so encode if it is not */
       if (!silc_utf8_valid(cmd->argv[i], cmd->argv_lens[i])) {
@@ -1196,7 +1239,7 @@ SILC_CLIENT_CMD_FUNC(join)
 
   /* Send JOIN command to the server */
   buffer =
-    silc_command_payload_encode_va(SILC_COMMAND_JOIN, 0, 7,
+    silc_command_payload_encode_va(SILC_COMMAND_JOIN, ++conn->cmd_ident, 7,
                                   1, name, strlen(name),
                                   2, idp->data, idp->len,
                                   3, passphrase, passphrase_len,
@@ -1247,11 +1290,13 @@ SILC_CLIENT_CMD_FUNC(motd)
 
   /* Send TOPIC command to the server */
   if (cmd->argc == 1)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 0, 1,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD,
+                                           ++conn->cmd_ident, 1,
                                            1, conn->remote_host,
                                            strlen(conn->remote_host));
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 0, 1,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD,
+                                           ++conn->cmd_ident, 1,
                                            1, cmd->argv[1],
                                            cmd->argv_lens[1]);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
@@ -1689,7 +1734,7 @@ SILC_CLIENT_CMD_FUNC(cmode)
      that requires an argument. */
   if (type && arg) {
     buffer =
-      silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 4,
+      silc_command_payload_encode_va(SILC_COMMAND_CMODE, ++conn->cmd_ident, 4,
                                     1, chidp->data, chidp->len,
                                     2, modebuf, sizeof(modebuf),
                                     type, arg, arg_len,
@@ -1697,7 +1742,7 @@ SILC_CLIENT_CMD_FUNC(cmode)
                                     pk ? pk->len : 0);
   } else {
     buffer =
-      silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 2,
+      silc_command_payload_encode_va(SILC_COMMAND_CMODE, ++conn->cmd_ident, 2,
                                     1, chidp->data, chidp->len,
                                     2, modebuf, sizeof(modebuf));
   }
@@ -1885,7 +1930,8 @@ SILC_CLIENT_CMD_FUNC(cumode)
 
   /* Send the command packet. We support sending only one mode at once
      that requires an argument. */
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE, 0,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE,
+                                         ++conn->cmd_ident,
                                          auth ? 4 : 3,
                                          1, chidp->data, chidp->len,
                                          2, modebuf, 4,
@@ -1916,7 +1962,6 @@ SILC_CLIENT_CMD_FUNC(kick)
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClient client = cmd->client;
   SilcClientConnection conn = cmd->conn;
-  SilcIDCacheEntry id_cache = NULL;
   SilcChannelEntry channel;
   SilcBuffer buffer, idp, idp2;
   SilcClientEntry target;
@@ -1952,14 +1997,12 @@ SILC_CLIENT_CMD_FUNC(kick)
   }
 
   /* Get the Channel ID of the channel */
-  if (!silc_idcache_find_by_name_one(conn->internal->channel_cache,
-                                    name, &id_cache)) {
+  channel = silc_client_get_channel(cmd->client, conn, name);
+  if (!channel) {
     COMMAND_ERROR(SILC_STATUS_ERR_NOT_ON_CHANNEL);
     goto out;
   }
 
-  channel = (SilcChannelEntry)id_cache->context;
-
   /* Parse the typed nickname. */
   if (client->internal->params->nickname_parse)
     client->internal->params->nickname_parse(cmd->argv[2], &nickname);
@@ -1977,14 +2020,16 @@ SILC_CLIENT_CMD_FUNC(kick)
   }
 
   /* Send KICK command to the server */
-  idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
+  idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
   idp2 = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
   if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 0, 2,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK,
+                                           ++conn->cmd_ident, 2,
                                            1, idp->data, idp->len,
                                            2, idp2->data, idp2->len);
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 0, 3,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK,
+                                           ++conn->cmd_ident, 3,
                                            1, idp->data, idp->len,
                                            2, idp2->data, idp2->len,
                                            3, cmd->argv[3],
@@ -2024,7 +2069,8 @@ static void silc_client_command_oper_send(unsigned char *data,
                                    data, data_len);
   }
 
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER, 0, 2,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER,
+                                         ++conn->cmd_ident, 2,
                                          1, cmd->argv[1],
                                          strlen(cmd->argv[1]),
                                          2, auth ? auth->data : NULL,
@@ -2096,7 +2142,8 @@ static void silc_client_command_silcoper_send(unsigned char *data,
                                    data, data_len);
   }
 
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER, 0, 2,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER,
+                                         ++conn->cmd_ident, 2,
                                          1, cmd->argv[1],
                                          strlen(cmd->argv[1]),
                                          2, auth ? auth->data : NULL,
@@ -2277,8 +2324,10 @@ SILC_CLIENT_CMD_FUNC(watch)
 {
   SilcClientCommandContext cmd = (SilcClientCommandContext)context;
   SilcClientConnection conn = cmd->conn;
-  SilcBuffer buffer, idp = NULL;
+  SilcBuffer buffer, idp = NULL, args = NULL;
   int type = 0;
+  const char *pubkey = NULL;
+  bool pubkey_add = TRUE;
 
   if (!cmd->conn) {
     SILC_NOT_CONNECTED(cmd->client, cmd->conn);
@@ -2297,19 +2346,51 @@ SILC_CLIENT_CMD_FUNC(watch)
     type = 2;
   } else if (!strcasecmp(cmd->argv[1], "-del")) {
     type = 3;
+  } else if (!strcasecmp(cmd->argv[1], "-pubkey") && cmd->argc >= 3) {
+    type = 4;
+    pubkey = cmd->argv[2] + 1;
+    if (cmd->argv[2][0] == '-')
+      pubkey_add = FALSE;
   } else {
     COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
   }
 
+  if (pubkey) {
+    SilcPublicKey pk;
+
+    if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_PEM)) {
+      if (!silc_pkcs_load_public_key(pubkey, &pk, SILC_PKCS_FILE_BIN)) {
+       SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+           "Could not load public key %s, check the filename",
+           pubkey);
+       COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+       goto out;
+      }
+    }
+
+    args = silc_buffer_alloc_size(2);
+    silc_buffer_format(args,
+                      SILC_STR_UI_SHORT(1),
+                      SILC_STR_END);
+    buffer = silc_pkcs_public_key_payload_encode(pk);
+    args = silc_argument_payload_encode_one(args, buffer->data, buffer->len,
+                                           pubkey_add ? 0x00 : 0x01);
+    silc_buffer_free(buffer);
+    silc_pkcs_public_key_free(pk);
+  }
+
   buffer = silc_command_payload_encode_va(SILC_COMMAND_WATCH,
                                          ++conn->cmd_ident, 2,
                                          1, idp->data, idp->len,
-                                         type, cmd->argv[2],
+                                         type,
+                                         pubkey ? args->data : cmd->argv[2],
+                                         pubkey ? args->len :
                                          cmd->argv_lens[2]);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
   silc_buffer_free(buffer);
+  silc_buffer_free(args);
 
   /* Notify application */
   COMMAND(SILC_STATUS_OK);
@@ -2362,7 +2443,8 @@ SILC_CLIENT_CMD_FUNC(leave)
 
   /* Send LEAVE command to the server */
   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_LEAVE, 0, 1,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_LEAVE,
+                                         ++conn->cmd_ident, 1,
                                          1, idp->data, idp->len);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
@@ -2526,7 +2608,8 @@ SILC_CLIENT_CMD_FUNC(getkey)
     idp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
   }
 
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY, 0, 1,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY,
+                                         ++conn->cmd_ident, 1,
                                          1, idp->data, idp->len);
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
@@ -2635,12 +2718,14 @@ SILC_CLIENT_CMD_FUNC(connect)
   }
 
   if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 2,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT,
+                                           ++conn->cmd_ident, 2,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]),
                                            2, port, 4);
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 1,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT,
+                                           ++conn->cmd_ident, 1,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]));
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
@@ -2684,12 +2769,14 @@ SILC_CLIENT_CMD_FUNC(close)
   }
 
   if (cmd->argc == 3)
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 2,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE,
+                                           ++conn->cmd_ident, 2,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]),
                                            2, port, 4);
   else
-    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 1,
+    buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE,
+                                           ++conn->cmd_ident, 1,
                                            1, cmd->argv[1],
                                            strlen(cmd->argv[1]));
   silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
@@ -2734,7 +2821,7 @@ void silc_client_commands_register(SilcClient client)
   silc_list_init(client->internal->commands, struct SilcClientCommandStruct,
                 next);
 
-  SILC_CLIENT_CMD(whois, WHOIS, "WHOIS", 3);
+  SILC_CLIENT_CMD(whois, WHOIS, "WHOIS", 5);
   SILC_CLIENT_CMD(whowas, WHOWAS, "WHOWAS", 3);
   SILC_CLIENT_CMD(identify, IDENTIFY, "IDENTIFY", 3);
   SILC_CLIENT_CMD(nick, NICK, "NICK", 2);
index de06296d540c22c5b11c6ea349bee9e4da10ee70..c6c597de1cb49f038bb03bc0ca96935819c0fb00 100644 (file)
@@ -1,6 +1,6 @@
 /*
 
-  command.h 
+  command.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
@@ -122,7 +122,7 @@ void silc_client_command_pending_del(SilcClientConnection conn,
 SilcClientCommandPendingCallbacks
 silc_client_command_pending_check(SilcClientConnection conn,
                                  SilcClientCommandReplyContext ctx,
-                                 SilcCommand command, 
+                                 SilcCommand command,
                                  SilcUInt16 ident,
                                  SilcUInt32 *callbacks_count);
 void silc_client_command_process(SilcClient client,
index a737af8d524f1bc1b498fac34504a7488cd421c4..3c041113b70157cc139bea90bbf6ef96dd56e9ca 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -160,7 +160,7 @@ void silc_client_command_reply_free(SilcClientCommandReplyContext cmd)
   }
 }
 
-static void
+void
 silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
                                     SilcStatus status,
                                     bool notify)
@@ -230,6 +230,11 @@ silc_client_command_reply_whois_save(SilcClientCommandReplyContext cmd,
     client_entry =
       silc_client_add_client(cmd->client, conn, nickname, username, realname,
                             client_id, mode);
+    if (!client_entry) {
+      if (notify)
+       COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+      return;
+    }
   } else {
     silc_client_update_client(cmd->client, conn, client_entry,
                              nickname, username, realname, mode);
@@ -413,6 +418,11 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
       client_entry =
        silc_client_add_client(cmd->client, conn, name, info, NULL,
                               silc_id_dup(client_id, id_type), 0);
+      if (!client_entry) {
+       if (notify)
+         COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+       return;
+      }
     } else {
       silc_client_update_client(cmd->client, conn, client_entry,
                                name, info, NULL, 0);
@@ -466,6 +476,11 @@ silc_client_command_reply_identify_save(SilcClientCommandReplyContext cmd,
       /* Add new channel entry */
       channel_entry = silc_client_add_channel(client, conn, name, 0,
                                              channel_id);
+      if (!channel_entry) {
+       if (notify)
+         COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+       return;
+      }
       channel_id = NULL;
     }
 
@@ -580,9 +595,19 @@ SILC_CLIENT_CMD_REPLY_FUNC(nick)
       silc_free(conn->nickname);
     conn->nickname = strdup(tmp);
     conn->local_entry->nickname = conn->nickname;
+
+    /* Normalize nickname */
+    tmp = silc_identifier_check(conn->nickname, strlen(conn->nickname),
+                               SILC_STRING_UTF8, 128, NULL);
+    if (!tmp) {
+      COMMAND_REPLY_ERROR(SILC_STATUS_ERR_BAD_NICKNAME);
+      goto out;
+    }
+
     silc_client_nickname_format(cmd->client, conn, conn->local_entry);
-    silc_idcache_add(conn->internal->client_cache, strdup(tmp),
-                     conn->local_entry->id, conn->local_entry, 0, NULL);
+
+    silc_idcache_add(conn->internal->client_cache, tmp,
+                    conn->local_entry->id, conn->local_entry, 0, NULL);
   }
 
   /* Notify application */
@@ -609,7 +634,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(list)
 
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
   if (!tmp) {
-    COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    /* There were no channels in the network. */
+    COMMAND_REPLY((SILC_ARGS, NULL, NULL, 0));
     goto out;
   }
 
@@ -708,6 +734,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(topic)
     goto out;
   }
 
+  if (topic) {
+    silc_free(channel->topic);
+    channel->topic = silc_memdup(topic, strlen(topic));
+  }
+
   /* Notify application */
   COMMAND_REPLY((SILC_ARGS, channel, topic));
 
@@ -963,7 +994,6 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
   SilcUInt32 argc, mode = 0, len, list_count;
   char *topic, *tmp, *channel_name = NULL, *hmac;
   SilcBuffer keyp = NULL, client_id_list = NULL, client_mode_list = NULL;
-  SilcPublicKey founder_key = NULL;
   SilcBufferStruct chpklist;
   int i;
 
@@ -1035,8 +1065,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
     channel = silc_client_add_channel(cmd->client, conn, channel_name,
                                      mode, channel_id);
   }
+  if (!channel) {
+    COMMAND_REPLY_ERROR(SILC_STATUS_ERR_BAD_CHANNEL);
+    goto out;
+  }
 
   conn->current_channel = channel;
+  channel->mode = mode;
 
   /* Get hmac */
   hmac = silc_argument_get_arg_type(cmd->args, 11, NULL);
@@ -1097,6 +1132,8 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
       client_entry =
        silc_client_add_client(cmd->client, conn, NULL, NULL, NULL,
                               silc_id_dup(client_id, SILC_ID_CLIENT), 0);
+      if (!client_entry)
+       goto out;
     }
 
     /* Join client to the channel */
@@ -1119,30 +1156,45 @@ SILC_CLIENT_CMD_REPLY_FUNC(join)
                   client_mode_list->head);
 
   /* Save channel key */
-  if (keyp && !(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
+  if (keyp)
     silc_client_save_channel_key(cmd->client, conn, keyp, channel);
 
   /* Get founder key */
   tmp = silc_argument_get_arg_type(cmd->args, 15, &len);
-  if (tmp)
-    silc_pkcs_public_key_payload_decode(tmp, len, &founder_key);
+  if (tmp) {
+    if (channel->founder_key)
+      silc_pkcs_public_key_free(channel->founder_key);
+    channel->founder_key = NULL;
+    silc_pkcs_public_key_payload_decode(tmp, len, &channel->founder_key);
+  }
+
+  /* Get user limit */
+  tmp = silc_argument_get_arg_type(cmd->args, 17, &len);
+  if (tmp && len == 4)
+    SILC_GET32_MSB(channel->user_limit, tmp);
+  if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT))
+    channel->user_limit = 0;
 
   /* Get channel public key list */
   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
   if (tmp)
     silc_buffer_set(&chpklist, tmp, len);
 
+  if (topic) {
+    silc_free(channel->topic);
+    channel->topic = silc_memdup(topic, strlen(topic));
+  }
+
   /* Notify application */
   COMMAND_REPLY((SILC_ARGS, channel_name, channel, mode, 0,
                 keyp ? keyp->head : NULL, NULL,
                 NULL, topic, hmac, list_count, client_id_list,
-                client_mode_list, founder_key, tmp ? &chpklist : NULL));
+                client_mode_list, channel->founder_key,
+                tmp ? &chpklist : NULL, channel->user_limit));
 
  out:
   SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_JOIN);
   silc_client_command_reply_free(cmd);
-  if (founder_key)
-    silc_pkcs_public_key_free(founder_key);
   silc_buffer_free(keyp);
   silc_buffer_free(client_id_list);
   silc_buffer_free(client_mode_list);
@@ -1294,6 +1346,13 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode)
       public_key = NULL;
   }
 
+  /* Get user limit */
+  tmp = silc_argument_get_arg_type(cmd->args, 6, &len);
+  if (tmp && len == 4)
+    SILC_GET32_MSB(channel->user_limit, tmp);
+  if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT))
+    channel->user_limit = 0;
+
   /* Get channel public key(s) */
   tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
   if (tmp)
@@ -1301,7 +1360,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(cmode)
 
   /* Notify application */
   COMMAND_REPLY((SILC_ARGS, channel, mode, public_key,
-                tmp ? &channel_pubkeys : NULL));
+                tmp ? &channel_pubkeys : NULL, channel->user_limit));
 
   silc_free(channel_id);
 
@@ -1933,6 +1992,11 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
       public_key = NULL;
   }
 
+  if (!public_key) {
+    COMMAND_REPLY_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+
   id_type = silc_id_payload_get_type(idp);
   if (id_type == SILC_ID_CLIENT) {
     /* Received client's public key */
@@ -1950,9 +2014,14 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
       silc_hash_make(cmd->client->sha1hash, tmp + 4, len - 4,
                     client_entry->fingerprint);
     }
+    if (!client_entry->public_key) {
+      client_entry->public_key = public_key;
+      public_key = NULL;
+    }
 
     /* Notify application */
-    COMMAND_REPLY((SILC_ARGS, id_type, client_entry, public_key));
+    COMMAND_REPLY((SILC_ARGS, id_type, client_entry,
+                  client_entry->public_key));
   } else if (id_type == SILC_ID_SERVER) {
     /* Received server's public key */
     server_id = silc_id_payload_get_id(idp);
index dfdfc6f3e5d4420367acfcd94dd0e74d5939cea7..8862a266fa1c201779adda35e953361447611b56 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2003 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -48,18 +48,28 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client,
   SilcClientEntry entry, *clients;
   int i = 0;
   bool found = FALSE;
+  char *nicknamec;
 
   assert(client && conn);
   if (!nickname)
     return NULL;
 
+  /* Normalize nickname for search */
+  nicknamec = silc_identifier_check(nickname, strlen(nickname),
+                                   SILC_STRING_UTF8, 128, NULL);
+  if (!nicknamec)
+    return NULL;
+
   /* Find ID from cache */
-  if (!silc_idcache_find_by_name(conn->internal->client_cache,
-                                (char *)nickname, &list))
+  if (!silc_idcache_find_by_name(conn->internal->client_cache, nicknamec,
+                                &list)) {
+    silc_free(nicknamec);
     return NULL;
+  }
 
   if (!silc_idcache_list_count(list)) {
     silc_idcache_list_free(list);
+    silc_free(nicknamec);
     return NULL;
   }
 
@@ -80,7 +90,7 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client,
     silc_idcache_list_first(list, &id_cache);
     while (id_cache) {
       entry = (SilcClientEntry)id_cache->context;
-      if (strcasecmp(entry->nickname, format)) {
+      if (!silc_utf8_strcasecmp(entry->nickname, format)) {
        if (!silc_idcache_list_next(list, &id_cache)) {
          break;
        } else {
@@ -95,6 +105,8 @@ SilcClientEntry *silc_client_get_clients_local(SilcClient client,
     }
   }
 
+  silc_free(nicknamec);
+
   if (list)
     silc_idcache_list_free(list);
 
@@ -121,9 +133,12 @@ typedef struct {
   SilcGetClientCallback completion;
   void *context;
   char *nickname;
-  char *server;
+  SilcClientEntry *clients;
+  SilcUInt32 clients_count;
 } *GetClientInternal;
 
+/* Completion for IDENTIFY */
+
 SILC_CLIENT_CMD_FUNC(get_client_callback)
 {
   GetClientInternal i = (GetClientInternal)context;
@@ -132,7 +147,7 @@ SILC_CLIENT_CMD_FUNC(get_client_callback)
 
   /* Get the clients */
   clients = silc_client_get_clients_local(i->client, i->conn,
-                                         i->nickname, i->server,
+                                         i->nickname, NULL,
                                          &clients_count);
   if (clients) {
     i->completion(i->client, i->conn, clients, clients_count, i->context);
@@ -142,10 +157,126 @@ SILC_CLIENT_CMD_FUNC(get_client_callback)
   }
 
   silc_free(i->nickname);
-  silc_free(i->server);
   silc_free(i);
 }
 
+/* Completion for WHOIS */
+
+SILC_CLIENT_CMD_FUNC(get_client_callback_wc)
+{
+  GetClientInternal i = (GetClientInternal)context;
+  SilcClientCommandReplyContext cmd = context2;
+  SilcClientID *client_id = NULL;
+  SilcClientEntry client_entry = NULL;
+  unsigned char *id_data;
+  SilcUInt32 len;
+
+  /* Get the client entry just returned from server */
+  id_data = silc_argument_get_arg_type(cmd->args, 2, &len);
+  if (id_data)
+    client_id = silc_id_payload_parse_id(id_data, len, NULL);
+  if (client_id)
+    client_entry = silc_client_get_client_by_id(i->client,
+                                               i->conn, client_id);
+  if (!client_entry) {
+    if (!SILC_STATUS_IS_ERROR(cmd->status) &&
+       cmd->status != SILC_STATUS_OK &&
+       cmd->status != SILC_STATUS_LIST_END) {
+      silc_free(client_id);
+      return;
+    }
+
+    i->completion(i->client, i->conn, i->clients, i->clients_count,
+                 i->context);
+    silc_free(client_id);
+    silc_free(i->clients);
+    silc_free(i->nickname);
+    silc_free(i);
+    return;
+  }
+
+  /* Save the client */
+  i->clients = silc_realloc(i->clients,
+                           (sizeof(*i->clients) * (i->clients_count + 1)));
+  i->clients[i->clients_count] = client_entry;
+  i->clients_count++;
+
+  /* Return if more data is expected */
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
+    silc_free(client_id);
+    return;
+  }
+
+  i->completion(i->client, i->conn, i->clients, i->clients_count,
+               i->context);
+
+  silc_free(client_id);
+  silc_free(i->clients);
+  silc_free(i->nickname);
+  silc_free(i);
+}
+
+/* Our own WHOIS reply processor. */
+
+SILC_CLIENT_CMD_FUNC(get_client_callback_w)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcClientConnection conn = (SilcClientConnection)cmd->sock->user_data;
+
+  SILC_LOG_DEBUG(("Start"));
+
+  if (!silc_command_get_status(cmd->payload, NULL, NULL)) {
+    if (SILC_STATUS_IS_ERROR(cmd->status))
+      goto out;
+    if (cmd->status == SILC_STATUS_LIST_END)
+      goto out;
+    goto err;
+  }
+
+  /* Save WHOIS info */
+  silc_client_command_reply_whois_save(cmd, cmd->status, FALSE);
+
+  /* Call pending completion for each reply */
+  if (cmd->status != SILC_STATUS_OK &&
+      cmd->status != SILC_STATUS_LIST_END) {
+    if (cmd->callbacks[0].callback)
+      (*cmd->callbacks[0].callback)(cmd->callbacks[0].context, cmd);
+    silc_client_command_reply_free(cmd);
+    return;
+  }
+
+ out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_WHOIS);
+
+ err:
+  /* If we received notify for invalid ID we'll remove the ID if we
+     have it cached. */
+  if (cmd->error == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
+    SilcClientEntry client_entry;
+    SilcUInt32 tmp_len;
+    unsigned char *tmp =
+      silc_argument_get_arg_type(silc_command_get_args(cmd->payload),
+                                2, &tmp_len);
+    if (tmp) {
+      SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+      if (client_id) {
+       client_entry = silc_client_get_client_by_id(cmd->client, conn,
+                                                   client_id);
+       if (client_entry)
+         silc_client_del_client(cmd->client, conn, client_entry);
+       silc_free(client_id);
+      }
+    }
+  }
+
+  /* Unregister this command reply */
+  silc_client_command_unregister(cmd->client, SILC_COMMAND_WHOIS,
+                                NULL, silc_client_command_reply_whois_i,
+                                cmd->ident);
+  silc_client_command_reply_free(cmd);
+}
+
 /* Finds client entry or entries by the `nickname' and `server'. The
    completion callback will be called when the client entries has been found.
 
@@ -155,27 +286,28 @@ SILC_CLIENT_CMD_FUNC(get_client_callback)
    get the client entry since this function may be very slow and should
    be used only to initially get the client entries. */
 
-void silc_client_get_clients(SilcClient client,
-                            SilcClientConnection conn,
-                            const char *nickname,
-                            const char *server,
-                            SilcGetClientCallback completion,
-                            void *context)
+void silc_client_get_clients_i(SilcClient client,
+                              SilcClientConnection conn,
+                              SilcCommand command,
+                              const char *nickname,
+                              const char *server,
+                              SilcBuffer attributes,
+                              SilcGetClientCallback completion,
+                              void *context)
 {
   GetClientInternal i;
   int len;
-  char *userhost;
+  char *userhost = NULL;
 
   assert(client && conn);
 
-  if (!nickname)
+  if (!nickname && !attributes)
     return;
 
   i = silc_calloc(1, sizeof(*i));
   i->client = client;
   i->conn = conn;
-  i->nickname = strdup(nickname);
-  i->server = server ? strdup(server) : NULL;
+  i->nickname = nickname ? strdup(nickname) : NULL;
   i->completion = completion;
   i->context = context;
 
@@ -185,26 +317,65 @@ void silc_client_get_clients(SilcClient client,
     silc_strncat(userhost, len, nickname, strlen(nickname));
     silc_strncat(userhost, len, "@", 1);
     silc_strncat(userhost, len, server, strlen(server));
-  } else {
+  } else if (nickname) {
     userhost = silc_memdup(nickname, strlen(nickname));
   }
 
   /* Register our own command reply for this command */
-  silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
-                              silc_client_command_reply_identify_i, 0,
-                              ++conn->cmd_ident);
-
-  /* Send the command */
-  silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
-                          conn->cmd_ident, 1, 1, userhost,
-                          strlen(userhost));
+  if (command == SILC_COMMAND_IDENTIFY) {
+    silc_client_command_register(client, command, NULL, NULL,
+                                silc_client_command_reply_identify_i, 0,
+                                ++conn->cmd_ident);
+    /* Send the command */
+    silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
+                            conn->cmd_ident, 1, 1, userhost,
+                            strlen(userhost));
+
+    /* Add pending callback */
+    silc_client_command_pending(conn, command, conn->cmd_ident,
+                               silc_client_command_get_client_callback,
+                               (void *)i);
+  } else {
+    silc_client_command_register(client, command, NULL, NULL,
+                                silc_client_command_get_client_callback_w, 0,
+                                ++conn->cmd_ident);
+    /* Send the command */
+    silc_client_command_send(client, conn, command, conn->cmd_ident, 2,
+                            1, userhost, userhost ? strlen(userhost) : 0,
+                            3, attributes ? attributes->data : NULL,
+                            attributes ? attributes->len : 0);
+
+    /* Add pending callback */
+    silc_client_command_pending(conn, command, conn->cmd_ident,
+                               silc_client_command_get_client_callback_wc,
+                               (void *)i);
+  }
+  silc_free(userhost);
+}
 
-  /* Add pending callback */
-  silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident,
-                             silc_client_command_get_client_callback,
-                             (void *)i);
+void silc_client_get_clients(SilcClient client,
+                            SilcClientConnection conn,
+                            const char *nickname,
+                            const char *server,
+                            SilcGetClientCallback completion,
+                            void *context)
+{
+  silc_client_get_clients_i(client, conn, SILC_COMMAND_IDENTIFY,
+                           nickname, server, NULL,
+                           completion, context);
+}
 
-  silc_free(userhost);
+void silc_client_get_clients_whois(SilcClient client,
+                                  SilcClientConnection conn,
+                                  const char *nickname,
+                                  const char *server,
+                                  SilcBuffer attributes,
+                                  SilcGetClientCallback completion,
+                                  void *context)
+{
+  silc_client_get_clients_i(client, conn, SILC_COMMAND_WHOIS,
+                           nickname, server, attributes,
+                           completion, context);
 }
 
 /* The old style function to find client entry. This is used by the
@@ -222,12 +393,19 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
   SilcIDCacheEntry id_cache;
   SilcIDCacheList list = NULL;
   SilcClientEntry entry = NULL;
+  char *nicknamec;
 
   SILC_LOG_DEBUG(("Start"));
 
+  /* Normalize nickname for search */
+  nicknamec = silc_identifier_check(nickname, strlen(nickname),
+                                   SILC_STRING_UTF8, 128, NULL);
+  if (!nicknamec)
+    return NULL;
+
   /* Find ID from cache */
   if (!silc_idcache_find_by_name(conn->internal->client_cache,
-                                (char *)nickname, &list)) {
+                                nicknamec, &list)) {
   identify:
 
     if (query) {
@@ -246,8 +424,11 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
       if (list)
        silc_idcache_list_free(list);
 
+      silc_free(nicknamec);
       return NULL;
     }
+
+    silc_free(nicknamec);
     return NULL;
   }
 
@@ -263,7 +444,7 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
     while (id_cache) {
       entry = (SilcClientEntry)id_cache->context;
 
-      if (strcasecmp(entry->nickname, format)) {
+      if (!silc_utf8_strcasecmp(entry->nickname, format)) {
        if (!silc_idcache_list_next(list, &id_cache)) {
          entry = NULL;
          break;
@@ -281,6 +462,8 @@ SilcClientEntry silc_idlist_get_client(SilcClient client,
       goto identify;
   }
 
+  silc_free(nicknamec);
+
   if (list)
     silc_idcache_list_free(list);
 
@@ -517,12 +700,18 @@ SILC_CLIENT_CMD_FUNC(get_clients_by_channel_cb)
   SilcHashTableList htl;
   SilcChannelUser chu;
 
+  if (i->res_count) {
+    i->res_count--;
+    if (i->res_count)
+      return;
+  }
+
   channel = silc_client_get_channel_by_id(i->client, i->conn, &i->channel_id);
   if (channel && !silc_hash_table_count(channel->user_list)) {
     clients = silc_calloc(silc_hash_table_count(channel->user_list),
                          sizeof(*clients));
     silc_hash_table_list(channel->user_list, &htl);
-    while (silc_hash_table_get(&htl, NULL, (void **)&chu))
+    while (silc_hash_table_get(&htl, NULL, (void *)&chu))
       clients[clients_count++] = chu->client;
     silc_hash_table_list_reset(&htl);
     found = TRUE;
@@ -583,7 +772,7 @@ void silc_client_get_clients_by_channel(SilcClient client,
   }
 
   silc_hash_table_list(channel->user_list, &htl);
-  while (silc_hash_table_get(&htl, NULL, (void **)&chu)) {
+  while (silc_hash_table_get(&htl, NULL, (void *)&chu)) {
     entry = chu->client;
 
     /* If the entry has incomplete info, then resolve it from the server. */
@@ -795,12 +984,30 @@ silc_client_add_client(SilcClient client, SilcClientConnection conn,
   client_entry->channels = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL,
                                                 NULL, NULL, NULL, TRUE);
 
+  /* Normalize nickname */
+  if (client_entry->nickname) {
+    silc_free(nick);
+    nick = silc_identifier_check(client_entry->nickname,
+                                strlen(client_entry->nickname),
+                                SILC_STRING_UTF8, 128, NULL);
+    if (!nick) {
+      silc_free(client_entry->nickname);
+      silc_free(client_entry->username);
+      silc_free(client_entry->hostname);
+      silc_free(client_entry->server);
+      silc_hash_table_free(client_entry->channels);
+      silc_free(client_entry);
+      return NULL;
+    }
+  }
+
   /* Format the nickname */
   silc_client_nickname_format(client, conn, client_entry);
 
   /* Add client to cache, the non-formatted nickname is saved to cache */
   if (!silc_idcache_add(conn->internal->client_cache, nick, client_entry->id,
                        (void *)client_entry, 0, NULL)) {
+    silc_free(nick);
     silc_free(client_entry->nickname);
     silc_free(client_entry->username);
     silc_free(client_entry->hostname);
@@ -840,6 +1047,16 @@ void silc_client_update_client(SilcClient client,
   if (!client_entry->nickname && nickname) {
     silc_parse_userfqdn(nickname, &nick, &client_entry->server);
     client_entry->nickname = strdup(nick);
+
+    /* Normalize nickname */
+    silc_free(nick);
+    nick = silc_identifier_check(client_entry->nickname,
+                                strlen(client_entry->nickname),
+                                SILC_STRING_UTF8, 128, NULL);
+    if (!nick)
+      return;
+
+    /* Format nickname */
     silc_client_nickname_format(client, conn, client_entry);
   }
   client_entry->mode = mode;
@@ -867,6 +1084,8 @@ void silc_client_del_client_entry(SilcClient client,
   silc_free(client_entry->server);
   silc_free(client_entry->id);
   silc_free(client_entry->fingerprint);
+  if (client_entry->public_key)
+    silc_pkcs_public_key_free(client_entry->public_key);
   silc_hash_table_free(client_entry->channels);
   if (client_entry->send_key)
     silc_cipher_free(client_entry->send_key);
@@ -907,6 +1126,7 @@ SilcChannelEntry silc_client_add_channel(SilcClient client,
                                         SilcChannelID *channel_id)
 {
   SilcChannelEntry channel;
+  char *channel_namec;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -917,9 +1137,20 @@ SilcChannelEntry silc_client_add_channel(SilcClient client,
   channel->user_list = silc_hash_table_alloc(1, silc_hash_ptr, NULL, NULL,
                                             NULL, NULL, NULL, TRUE);
 
+  /* Normalize channel name */
+  channel_namec = silc_channel_name_check(channel_name, strlen(channel_name),
+                                         SILC_STRING_UTF8, 256, NULL);
+  if (!channel_namec) {
+    silc_free(channel->channel_name);
+    silc_hash_table_free(channel->user_list);
+    silc_free(channel);
+    return NULL;
+  }
+
   /* Put it to the ID cache */
-  if (!silc_idcache_add(conn->internal->channel_cache, channel->channel_name,
+  if (!silc_idcache_add(conn->internal->channel_cache, channel_namec,
                        (void *)channel->id, (void *)channel, 0, NULL)) {
+    silc_free(channel_namec);
     silc_free(channel->channel_name);
     silc_hash_table_free(channel->user_list);
     silc_free(channel);
@@ -963,7 +1194,10 @@ bool silc_client_del_channel(SilcClient client, SilcClientConnection conn,
   silc_hash_table_free(channel->user_list);
 
   silc_free(channel->channel_name);
+  silc_free(channel->topic);
   silc_free(channel->id);
+  if (channel->founder_key)
+    silc_pkcs_public_key_free(channel->founder_key);
   silc_free(channel->key);
   if (channel->channel_key)
     silc_cipher_free(channel->channel_key);
@@ -983,6 +1217,7 @@ bool silc_client_del_channel(SilcClient client, SilcClientConnection conn,
       silc_hmac_free(hmac);
     silc_dlist_uninit(channel->old_hmacs);
   }
+  silc_schedule_task_del_by_context(conn->client->schedule, channel);
   silc_client_del_channel_private_keys(client, conn, channel);
   silc_free(channel);
   return ret;
@@ -996,6 +1231,8 @@ bool silc_client_replace_channel_id(SilcClient client,
                                    SilcChannelEntry channel,
                                    SilcChannelID *new_id)
 {
+  char *channel_namec;
+
   if (!new_id)
     return FALSE;
 
@@ -1007,8 +1244,15 @@ bool silc_client_replace_channel_id(SilcClient client,
   silc_idcache_del_by_id(conn->internal->channel_cache, channel->id);
   silc_free(channel->id);
   channel->id = new_id;
-  return silc_idcache_add(conn->internal->channel_cache,
-                         channel->channel_name,
+
+  /* Normalize channel name */
+  channel_namec = silc_channel_name_check(channel->channel_name,
+                                         strlen(channel->channel_name),
+                                         SILC_STRING_UTF8, 256, NULL);
+  if (!channel_namec)
+    return FALSE;
+
+  return silc_idcache_add(conn->internal->channel_cache, channel_namec,
                          (void *)channel->id, (void *)channel, 0, NULL);
 
 }
@@ -1030,14 +1274,24 @@ SilcChannelEntry silc_client_get_channel(SilcClient client,
 
   SILC_LOG_DEBUG(("Start"));
 
+  /* Normalize name for search */
+  channel = silc_channel_name_check(channel, strlen(channel), SILC_STRING_UTF8,
+                                   256, NULL);
+  if (!channel)
+    return NULL;
+
   if (!silc_idcache_find_by_name_one(conn->internal->channel_cache, channel,
-                                    &id_cache))
+                                    &id_cache)) {
+    silc_free(channel);
     return NULL;
+  }
 
   entry = (SilcChannelEntry)id_cache->context;
 
   SILC_LOG_DEBUG(("Found"));
 
+  silc_free(channel);
+
   return entry;
 }
 
@@ -1208,12 +1462,22 @@ SilcServerEntry silc_client_get_server(SilcClient client,
 
   SILC_LOG_DEBUG(("Start"));
 
+  /* Normalize server name for search */
+  server_name = silc_identifier_check(server_name, strlen(server_name),
+                                     SILC_STRING_UTF8, 256, NULL);
+  if (!server_name)
+    return NULL;
+
   if (!silc_idcache_find_by_name_one(conn->internal->server_cache,
-                                    server_name, &id_cache))
+                                    server_name, &id_cache)) {
+    silc_free(server_name);
     return NULL;
+  }
 
   entry = (SilcServerEntry)id_cache->context;
 
+  silc_free(server_name);
+
   return entry;
 }
 
@@ -1250,6 +1514,7 @@ SilcServerEntry silc_client_add_server(SilcClient client,
                                       SilcServerID *server_id)
 {
   SilcServerEntry server_entry;
+  char *server_namec = NULL;
 
   SILC_LOG_DEBUG(("Start"));
 
@@ -1263,10 +1528,23 @@ SilcServerEntry silc_client_add_server(SilcClient client,
   if (server_info)
     server_entry->server_info = strdup(server_info);
 
+  /* Normalize server name */
+  if (server_name) {
+    server_namec = silc_identifier_check(server_name, strlen(server_name),
+                                        SILC_STRING_UTF8, 256, NULL);
+    if (!server_namec) {
+      silc_free(server_entry->server_id);
+      silc_free(server_entry->server_name);
+      silc_free(server_entry->server_info);
+      silc_free(server_entry);
+      return NULL;
+    }
+  }
+
   /* Add server to cache */
-  if (!silc_idcache_add(conn->internal->server_cache,
-                       server_entry->server_name,
+  if (!silc_idcache_add(conn->internal->server_cache, server_namec,
                        server_entry->server_id, server_entry, 0, NULL)) {
+    silc_free(server_namec);
     silc_free(server_entry->server_id);
     silc_free(server_entry->server_name);
     silc_free(server_entry->server_info);
@@ -1298,21 +1576,34 @@ void silc_client_update_server(SilcClient client,
                               const char *server_name,
                               const char *server_info)
 {
+  char *server_namec = NULL;
+
   SILC_LOG_DEBUG(("Start"));
 
-  if (server_name && (!server_entry->server_name ||
-                     strcmp(server_entry->server_name, server_name))) {
+  if (server_name &&
+      (!server_entry->server_name ||
+       !silc_utf8_strcasecmp(server_entry->server_name, server_name))) {
 
     silc_idcache_del_by_context(conn->internal->server_cache, server_entry);
     silc_free(server_entry->server_name);
     server_entry->server_name = strdup(server_name);
-    silc_idcache_add(conn->internal->server_cache, server_entry->server_name,
-                    server_entry->server_id,
-                    server_entry, 0, NULL);
+
+    /* Normalize server name */
+    if (server_name) {
+      server_namec = silc_identifier_check(server_name, strlen(server_name),
+                                          SILC_STRING_UTF8, 256, NULL);
+      if (!server_namec)
+       return;
+
+      silc_idcache_add(conn->internal->server_cache, server_namec,
+                      server_entry->server_id,
+                      server_entry, 0, NULL);
+    }
   }
 
-  if (server_info && (!server_entry->server_info ||
-                     strcmp(server_entry->server_info, server_info))) {
+  if (server_info &&
+      (!server_entry->server_info ||
+       !silc_utf8_strcasecmp(server_entry->server_info, server_info))) {
     silc_free(server_entry->server_info);
     server_entry->server_info = strdup(server_info);
   }
@@ -1358,7 +1649,7 @@ void silc_client_nickname_format(SilcClient client,
     if (clients[i]->valid && clients[i] != client_entry)
       len++;
     if (clients[i]->valid && clients[i] != client_entry &&
-       !strcmp(clients[i]->nickname, client_entry->nickname))
+       silc_utf8_strcasecmp(clients[i]->nickname, client_entry->nickname))
       freebase = FALSE;
   }
   if (!len || freebase)
@@ -1368,8 +1659,8 @@ void silc_client_nickname_format(SilcClient client,
     unformatted = clients[0];
   else
     for (i = 0; i < clients_count; i++)
-      if (!strncasecmp(clients[i]->nickname, client_entry->nickname,
-                      strlen(clients[i]->nickname)))
+      if (silc_utf8_strncasecmp(clients[i]->nickname, client_entry->nickname,
+                               strlen(clients[i]->nickname)))
        unformatted = clients[i];
 
   /* If we are changing nickname of our local entry we'll enforce
@@ -1444,7 +1735,7 @@ void silc_client_nickname_format(SilcClient client,
          break;
 
        for (i = 0; i < clients_count; i++) {
-         if (strncasecmp(clients[i]->nickname, newnick, off))
+         if (!silc_utf8_strncasecmp(clients[i]->nickname, newnick, off))
            continue;
          if (strlen(clients[i]->nickname) <= off)
            continue;
index bc229606f6b0f19b2baa618bcac556730b2a05fb..b3cbe4a53c1b5696cae76c0a938382f27d633970 100644 (file)
@@ -2,14 +2,13 @@
 
   protocol.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,9 +16,6 @@
   GNU General Public License for more details.
 
 */
-/*
- * Client side of the protocols.
- */
 /* $Id$ */
 
 #include "silcincludes.h"
@@ -633,7 +629,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_connection_auth)
        */
       unsigned char *auth_data = NULL;
       SilcUInt32 auth_data_len = 0;
-      unsigned char sign[1024];
+      unsigned char sign[2048 + 1];
 
       switch(ctx->auth_meth) {
       case SILC_AUTH_NONE:
@@ -938,6 +934,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
           */
 
          /* Send the REKEY_DONE to indicate we will take new keys into use */
+         silc_client_packet_queue_purge(client, ctx->sock);
          silc_client_packet_send(client, ctx->sock,
                                  SILC_PACKET_REKEY_DONE,
                                  NULL, 0, NULL, NULL, NULL, 0, FALSE);
@@ -995,6 +992,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
 
          /* Send the REKEY_DONE to indicate we will take new keys into use
             now. */
+         silc_client_packet_queue_purge(client, ctx->sock);
          silc_client_packet_send(client, ctx->sock,
                                  SILC_PACKET_REKEY_DONE,
                                  NULL, 0, NULL, NULL, NULL, 0, FALSE);
@@ -1060,6 +1058,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
 
     /* Send the REKEY_DONE to indicate we will take new keys into use
        now. */
+    silc_client_packet_queue_purge(client, ctx->sock);
     silc_client_packet_send(client, ctx->sock, SILC_PACKET_REKEY_DONE,
                            NULL, 0, NULL, NULL, NULL, 0, FALSE);
 
@@ -1067,6 +1066,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
        key to the new key since all packets after this packet must
        encrypted with the new key. */
     silc_client_protocol_rekey_generate_pfs(client, ctx, TRUE);
+    silc_client_packet_queue_purge(client, ctx->sock);
 
     /* The protocol ends in next stage. */
     protocol->state = SILC_PROTOCOL_STATE_END;
@@ -1089,6 +1089,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_rekey)
       silc_client_protocol_rekey_generate_pfs(client, ctx, FALSE);
     else
       silc_client_protocol_rekey_generate(client, ctx, FALSE);
+    silc_client_packet_queue_purge(client, ctx->sock);
 
     /* Protocol has ended, call the final callback */
     if (protocol->final_callback)
index 9d93709210bd550ea29801218564d2c1b3ec225e..019fa37adbc5af7364bacec5e30b73021c389b2a 100644 (file)
@@ -2,15 +2,14 @@
 
   protocol.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -52,6 +51,7 @@ typedef struct {
 typedef struct {
   void *client;
   SilcSocketConnection sock;
+  SilcClientConnectionStatus status;
 
   /* SKE object from Key Exchange protocol. */
   SilcSKE ske;
index e73e7945097b7b2119c237f4ca10fa53ac43d38d..a819389688367d837a29aa6e1aae473d964a72de 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2003 Pekka Riikonen
+  Copyright (C) 2000 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -42,9 +42,6 @@
  *   applications.  These functions are implemented in the SILC Client Library.
  *   Application may freely call these functions from the library.
  *
- * Please, refer to the README file in this directory for the directions
- * of how to use the SILC Client Library.
- *
  ***/
 
 #ifndef SILCCLIENT_H
@@ -76,7 +73,8 @@ extern "C" {
  */
 struct SilcClientStruct {
   /*
-   * The following fields are set by application
+   * The following fields are set by application. Strings MUST be UTF-8
+   * encoded strings.
    */
   char *nickname;               /* Nickname, MAY be set by application  */
   char *username;               /* Username, MUST be set by application */
@@ -126,7 +124,7 @@ struct SilcClientStruct {
  *    to server this is context is returned to the application in the
  *    "connected" client operation.  It includes all the important
  *    data for the session, such as nickname, local and remote IDs, and
- *    other information.
+ *    other information.  All strings in the structure are UTF-8 encoded.
  *
  * SOURCE
  */
@@ -143,7 +141,7 @@ struct SilcClientConnectionStruct {
   /*
    * Remote data
    */
-  char *remote_host;             /* Remote host name */
+  char *remote_host;             /* Remote host name, UTF-8 encoded */
   int remote_port;               /* Remote port */
   SilcServerID *remote_id;       /* Remote Server ID */
   unsigned char *remote_id_data;  /* Remote Server ID decoded */
@@ -193,7 +191,7 @@ struct SilcClientConnectionStruct {
  *    that are accessed using the Client Library routines will have their
  *    own SilcClientEntry structure.  For example, when finding users by
  *    their nickname the Client Library returns this structure back to
- *    the application.
+ *    the application.  All strings in the structure are UTF-8 encoded.
  *
  * SOURCE
  */
@@ -206,11 +204,12 @@ struct SilcClientEntryStruct {
   char *realname;              /* Realname (userinfo) */
 
   /* Mode, ID and other information */
-  SilcUInt32 mode;             /* User mode in SILC */
+  SilcUInt32 mode;             /* User mode in SILC, see SilcUserMode */
   SilcClientID *id;            /* The Client ID */
   SilcDList attrs;             /* Requested Attributes (maybe NULL) */
   unsigned char *fingerprint;  /* Fingerprint of client's public key */
   SilcUInt32 fingerprint_len;  /* Length of the fingerprint */
+  SilcPublicKey public_key;    /* User's public key, may be NULL */
 
   /* Private message keys */
   SilcCipher send_key;         /* Private message key for sending */
@@ -227,8 +226,13 @@ struct SilcClientEntryStruct {
   SilcEntryStatus status;      /* Status mask */
   SilcHashTable channels;      /* All channels client has joined */
   SilcUInt16 resolve_cmd_ident;        /* Command identifier when resolving */
-  bool generated;              /* TRUE if library generated `key' */
-  bool valid;                  /* FALSE if this entry is not valid */
+  unsigned int generated   : 1; /* TRUE if library generated `key' */
+  unsigned int valid       : 1;        /* FALSE if this entry is not valid */
+  unsigned int prv_resp    : 1; /* TRUE if private message key indicator
+                                  has been received (responder). */
+
+  /* Application specific data.  Application may set here whatever it wants. */
+  void *context;
 };
 /***/
 
@@ -243,7 +247,7 @@ struct SilcClientEntryStruct {
  *    This structure represents a channel in the SILC network.  All
  *    channels that the client are aware of or have joined in will be
  *    represented as SilcChannelEntry.  The structure includes information
- *    about the channel.
+ *    about the channel.  All strings in the structure are UTF-8 encoded.
  *
  * SOURCE
  */
@@ -251,7 +255,10 @@ struct SilcChannelEntryStruct {
   /* General information */
   char *channel_name;                       /* Channel name */
   SilcChannelID *id;                        /* Channel ID */
-  SilcUInt32 mode;                          /* Channel mode */
+  SilcUInt32 mode;                          /* Channel mode, ChannelModes. */
+  char *topic;                              /* Current topic, may be NULL */
+  SilcPublicKey founder_key;                /* Founder key, may be NULL */
+  SilcUInt32 user_limit;                    /* User limit on channel */
 
   /* All clients that has joined this channel.  The key to the table is the
      SilcClientEntry and the context is SilcChannelUser context. */
@@ -273,6 +280,33 @@ struct SilcChannelEntryStruct {
   SilcDList old_hmacs;
   SilcUInt16 resolve_cmd_ident;                     /* Command identifier when
                                                resolving this entry */
+
+  /* Application specific data.  Application may set here whatever it wants. */
+  void *context;
+};
+/***/
+
+/****s* silcclient/SilcClientAPI/SilcChannelUser
+ *
+ * NAME
+ *
+ *    typedef struct SilcChannelUserStruct { ... } *SilcChannelUser
+ *
+ * DESCRIPTION
+ *
+ *    This structure represents a client that has joined to a channel.
+ *    It shows the client and the channel and the client's mode (channel
+ *    user mode) on the channel.
+ *
+ * SOURCE
+ */
+struct SilcChannelUserStruct {
+  SilcClientEntry client;                   /* Client joined on channel */
+  SilcUInt32 mode;                          /* mode, ChannelUserModes */
+  SilcChannelEntry channel;                 /* The channel user has joined */
+
+  /* Application specific data.  Application may set here whatever it wants. */
+  void *context;
 };
 /***/
 
@@ -287,6 +321,7 @@ struct SilcChannelEntryStruct {
  *    This structure represents a server in the SILC network.  All servers
  *    that the client is aware of and have for example resolved with
  *    SILC_COMMAND_INFO command have their on SilcServerEntry structure.
+ *    All strings in the structure are UTF-8 encoded.
  *
  * SOURCE
  */
@@ -297,6 +332,9 @@ struct SilcServerEntryStruct {
   SilcServerID *server_id;                  /* Server ID */
   SilcUInt16 resolve_cmd_ident;                     /* Command identifier when
                                                resolving this entry */
+
+  /* Application specific data.  Application may set here whatever it wants. */
+  void *context;
 };
 /***/
 
@@ -494,7 +532,7 @@ typedef enum {
  * DESCRIPTION
  *
  *    This type is returned to the `connect' client operation to indicate
- *    the status of the created connection.  It can indicated if it was
+ *    the status of the created connection.  It can indicate if it was
  *    successful or whether an error occurred.
  *
  * SOURCE
@@ -503,7 +541,12 @@ typedef enum {
   SILC_CLIENT_CONN_SUCCESS,           /* Successfully connected */
   SILC_CLIENT_CONN_SUCCESS_RESUME,     /* Successfully connected and
                                          resumed old detached session */
-  SILC_CLIENT_CONN_ERROR,             /* Error occurred during connecting */
+  SILC_CLIENT_CONN_ERROR,             /* Unknown error occurred during
+                                         connecting */
+  SILC_CLIENT_CONN_ERROR_KE,          /* Key Exchange failed */
+  SILC_CLIENT_CONN_ERROR_AUTH,        /* Authentication failed */
+  SILC_CLIENT_CONN_ERROR_RESUME,       /* Resuming failed */
+  SILC_CLIENT_CONN_ERROR_TIMEOUT,      /* Timeout during connecting */
 } SilcClientConnectionStatus;
 /***/
 
@@ -539,7 +582,8 @@ typedef struct {
      (like it may tell the message is multimedia message). */
   void (*channel_message)(SilcClient client, SilcClientConnection conn,
                          SilcClientEntry sender, SilcChannelEntry channel,
-                         SilcMessagePayload payload, SilcMessageFlags flags,
+                         SilcMessagePayload payload,
+                         SilcChannelPrivateKey key, SilcMessageFlags flags,
                          const unsigned char *message,
                          SilcUInt32 message_len);
 
@@ -615,7 +659,9 @@ typedef struct {
   /* Called to indicate that connection was disconnected to the server.
      The `status' may tell the reason of the disconnection, and if the
      `message' is non-NULL it may include the disconnection message
-     received from server. */
+     received from server. Application must not call the
+     silc_client_close_connection in this callback.  The 'conn' is also
+     invalid after this function returns back to library. */
   void (*disconnected)(SilcClient client, SilcClientConnection conn,
                       SilcStatus status, const char *message);
 
@@ -807,6 +853,11 @@ typedef struct {
      silc_client_attribute_add for more information on attributes. */
   bool ignore_requested_attributes;
 
+  /* If this is set to TRUE, the silcclient library will not register and
+     deregister the cipher, pkcs, hash and hmac algorithms. The application
+     itself will need to handle that. */
+  bool dont_register_crypto_library;
+
 } SilcClientParams;
 /***/
 
@@ -1259,6 +1310,48 @@ void silc_client_get_clients(SilcClient client,
                             SilcGetClientCallback completion,
                             void *context);
 
+/****f* silcclient/SilcClientAPI/silc_client_get_clients_whois
+ *
+ * SYNOPSIS
+ *
+ *    void silc_client_get_clients_whois(SilcClient client,
+ *                                       SilcClientConnection conn,
+ *                                       const char *nickname,
+ *                                       const char *server,
+ *                                       SilcBuffer attributes,
+ *                                       SilcGetClientCallback completion,
+ *                                       void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Finds client entry or entries by the `nickname' and `server'. The
+ *    completion callback will be called when the client entries has been
+ *    found.  After the server returns the client information it is cached
+ *    and can be accesses locally at a later time.  The resolving is done
+ *    with WHOIS command.  The `server' may be NULL.
+ *
+ *    If the `attributes' is non-NULL then the buffer includes Requested
+ *    Attributes which can be used to fetch very detailed information
+ *    about the user. If it is NULL then only normal WHOIS query is
+ *    made (for more information about attributes see SilcAttribute).
+ *    Caller may create the `attributes' with silc_client_attributes_request
+ *    function.
+ *
+ * NOTES
+ *
+ *    The resolving is done with WHOIS command. For this reason this
+ *    command may take a long time because it resolves detailed user
+ *    information.
+ *
+ ***/
+void silc_client_get_clients_whois(SilcClient client,
+                                  SilcClientConnection conn,
+                                  const char *nickname,
+                                  const char *server,
+                                  SilcBuffer attributes,
+                                  SilcGetClientCallback completion,
+                                  void *context);
+
 /****f* silcclient/SilcClientAPI/silc_client_get_clients_local
  *
  * SYNOPSIS
@@ -1517,8 +1610,9 @@ void silc_client_get_channel_resolve(SilcClient client,
  *
  * DESCRIPTION
  *
- *    Finds channel entry by the channel name. Returns the entry or NULL
- *    if it was not found.
+ *    Finds channel entry by the channel ID. Returns the entry or NULL
+ *    if the entry was not found.  This checks the local cache and does
+ *    not resolve anything from server.
  *
  ***/
 SilcChannelEntry silc_client_get_channel_by_id(SilcClient client,
@@ -1678,6 +1772,14 @@ SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
  *                             NULL);
  *    silc_client_command_call(client, conn, "PING silc.silcnet.org");
  *
+ * NOTES
+ *
+ *    This command executes the commands implemented inside the client
+ *    library.  These commands are designed for command line applications,
+ *    but GUI application may call them too if needed.  Alternatively
+ *    application may override the library and use silc_client_command_send
+ *    function instead.
+ *
  ***/
 bool silc_client_command_call(SilcClient client,
                              SilcClientConnection conn,
@@ -1702,6 +1804,10 @@ bool silc_client_command_call(SilcClient client,
  *    Note that this overriders the Client Librarys commands and sends
  *    the command packet directly to server.
  *
+ *    Programmer should get familiar with the SILC protocol commands
+ *    specification when using this function, as the arguments needs to
+ *    be encoded as specified in the protocol.
+ *
  *    The variable arguments are a pair of { type, data, data_length },
  *    and the `argc' is the number of these pairs.
  *
@@ -1896,6 +2002,40 @@ silc_client_list_private_message_keys(SilcClient client,
                                      SilcClientConnection conn,
                                      SilcUInt32 *key_count);
 
+/****f* silcclient/SilcClientAPI/silc_client_send_private_message_key_request
+ *
+ * SYNOPSIS
+ *
+ *    bool
+ *    silc_client_send_private_message_key_request(SilcClient client,
+ *                                               SilcClientConnection conn,
+ *                                               SilcClientEntry client_entry);
+ *
+ * DESCRIPTION
+ *
+ *    This function can be used to send an private message key indicator
+ *    request to the remote client indicated by 'client_entry'.  This can
+ *    be used when setting a static or pre-shared private message key.
+ *    The sender of this packet is the initiator and must set the 'responder'
+ *    argument in silc_client_add_private_message_key function to FALSE.
+ *    The receiver of this indicator request must set it to TRUE, if the
+ *    receiver decides to set a private message key.  By using this
+ *    function applications may automate initiator/responder setting in
+ *    private message key functions, without asking from user which one is
+ *    the initiator and which one is responder.
+ *
+ * NOTES
+ *
+ *    The sender of this packet must set the private message key for
+ *    'client_entry' before calling this function.  The 'responder'
+ *    argument MUST be set to FALSE when setting the key.
+ *
+ ***/
+bool
+silc_client_send_private_message_key_request(SilcClient client,
+                                            SilcClientConnection conn,
+                                            SilcClientEntry client_entry);
+
 /****f* silcclient/SilcClientAPI/silc_client_free_private_message_keys
  *
  * SYNOPSIS
@@ -1927,18 +2067,22 @@ void silc_client_free_private_message_keys(SilcPrivateMessageKeys keys,
  *                                             char *cipher,
  *                                             char *hmac,
  *                                             unsigned char *key,
- *                                             SilcUInt32 key_len);
+ *                                             SilcUInt32 key_len,
+ *                                             SilcChannelPrivateKey *ret_key);
  *
  * DESCRIPTION
  *
- *    Adds private key for channel. This may be set only if the channel's mode
- *    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
- *    mode is not set. When channel has private key then the messages are
- *    encrypted using that key. All clients on the channel must also know the
- *    key in order to decrypt the messages. However, it is possible to have
- *    several private keys per one channel. In this case only some of the
- *    clients on the channel may know the one key and only some the other key.
- *    The `name' can be application given name for the key.
+ *    Adds private key for channel. When channel has private key then the
+ *    messages are encrypted using that key. All clients on the channel
+ *    must also know the key in order to decrypt the messages. However,
+ *    it is possible to have several private keys per one channel. In this
+ *    case only some of the clients on the channel may know the one key
+ *    and only some the other key.  The `name' can be application given
+ *    name for the key.  This returns the created key to the 'ret_key'
+ *    pointer if it is non-NULL;
+ *
+ *    If `cipher' and/or `hmac' is NULL then default values will be used
+ *    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
  *
  *    The private key for channel is optional. If it is not set then the
  *    channel messages are encrypted using the channel key generated by the
@@ -1968,7 +2112,8 @@ bool silc_client_add_channel_private_key(SilcClient client,
                                         char *cipher,
                                         char *hmac,
                                         unsigned char *key,
-                                        SilcUInt32 key_len);
+                                        SilcUInt32 key_len,
+                                        SilcChannelPrivateKey *ret_key);
 
 /****f* silcclient/SilcClientAPI/silc_client_del_channel_private_keys
  *
@@ -2404,6 +2549,54 @@ typedef void (*SilcClientFileMonitor)(SilcClient client,
                                      const char *filepath,
                                      void *context);
 
+/****f* silcclient/SilcClientAPI/SilcClientFileName
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcClientFileName)(const char *filepath,
+ *                                       void *context);
+ *
+ * DESCRIPTION
+ *
+ *    Completion callback for the SilcClientFileAskName callback function.
+ *    Application calls this to deliver the filepath and filename where
+ *    the downloaded file is to be saved.
+ *
+ ***/
+typedef void (*SilcClientFileName)(const char *filepath,
+                                  void *context);
+
+/****f* silcclient/SilcClientAPI/SilcClientFileAskName
+ *
+ * SYNOPSIS
+ *
+ *    typedef void (*SilcClientFileAskName)(SilcClient client,
+ *                                          SilcClientConnection conn,
+ *                                          SilcUInt32 session_id,
+ *                                          const char *remote_filename,
+ *                                          SilcClientFileName completion,
+ *                                          void *completion_context,
+ *                                          void *context);
+ *
+ * DESCRIPTION
+ *
+ *    File name asking callback, that is called if it is given to the
+ *    silc_client_file_receive and the path given to that as argument was
+ *    NULL.  The library calls this to ask the filename and filepath to
+ *    where the file is to be saved.  The 'remote_filename' is the file
+ *    that is being downloaded.  Application must call the 'completion'
+ *    with 'completion_context' to continue with the file downloading.
+ *    It is not mandatory to provide this to the silc_client_file_receive.
+ *
+ ***/
+typedef void (*SilcClientFileAskName)(SilcClient client,
+                                     SilcClientConnection conn,
+                                     SilcUInt32 session_id,
+                                     const char *remote_filename,
+                                     SilcClientFileName completion,
+                                     void *completion_context,
+                                     void *context);
+
 /****f* silcclient/SilcClientAPI/silc_client_file_send
  *
  * SYNOPSIS
@@ -2469,7 +2662,9 @@ silc_client_file_send(SilcClient client,
  *                             SilcClientFileMonitor monitor,
  *                             void *monitor_context,
  *                             const char *path,
- *                             SilcUInt32 session_id);
+ *                             SilcUInt32 session_id,
+ *                             SilcClientFileAskName ask_name,
+ *                             void *ask_name_context);
  *
  * DESCRIPTION
  *
@@ -2478,9 +2673,11 @@ silc_client_file_send(SilcClient client,
  *    received in the `ftp' client operation function.  This will actually
  *    perform the key agreement protocol with the remote client before
  *    actually starting the file transmission.  The `monitor' callback
- *    will be called to monitor the transmission.  If `path' is non NULL
+ *    will be called to monitor the transmission.  If `path' is non-NULL
  *    the file will be saved into that directory.  If NULL the file is
- *    saved in the current working directory.
+ *    saved in the current working directory, unless the 'ask_name'
+ *    callback is non-NULL.  In this case the callback is called to ask
+ *    the path and filename from application.
  *
  *    If error will occur during the file transfer process the error
  *    status will be returned in the monitor callback.  In this case
@@ -2494,7 +2691,9 @@ silc_client_file_receive(SilcClient client,
                         SilcClientFileMonitor monitor,
                         void *monitor_context,
                         const char *path,
-                        SilcUInt32 session_id);
+                        SilcUInt32 session_id,
+                        SilcClientFileAskName ask_name,
+                        void *ask_name_context);
 
 /****f* silcclient/SilcClientAPI/silc_client_file_close
  *
@@ -2510,7 +2709,10 @@ silc_client_file_receive(SilcClient client,
  *    If file transmission is being conducted it will be aborted
  *    automatically. This function is also used to close the session
  *    after successful file transmission. This function can be used
- *    also to reject incoming file transmission request.
+ *    also to reject incoming file transmission request.  If the
+ *    session was already started and the monitor callback was set
+ *    the monitor callback will be called with the monitor status
+ *    SILC_CLIENT_FILE_MONITOR_CLOSED.
  *
  ***/
 SilcClientFileError silc_client_file_close(SilcClient client,
@@ -2617,6 +2819,16 @@ const SilcHashTable silc_client_attributes_get(SilcClient client,
  *    You can give the returned buffer as argument to for example
  *    silc_client_get_client_by_id_resolve function.
  *
+ * EXAMPLE
+ *
+ *    Request all attributes
+ *    buffer = silc_client_attributes_request(0);
+ *
+ *    Request only the following attributes
+ *    buffer = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO,
+ *                                            SILC_ATTRIBUTE_SERVICE,
+ *                                            SILC_ATTRIBUTE_MOOD, 0);
+ *
  ***/
 SilcBuffer silc_client_attributes_request(SilcAttribute attribute, ...);
 
similarity index 82%
rename from lib/silccore/Makefile.am
rename to lib/silccore/Makefile.ad
index 7dae40126f105118794fa04d60a7521451d95abb..b5d6d71b277bed0a82eb8adf351016f4d481173d 100644 (file)
@@ -1,9 +1,9 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 - 2003 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@ libsilccore_la_SOURCES = \
        silcattrs.c \
        silcstatus.c
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS =      \
        silcauth.h      \
        silcchannel.h   \
@@ -46,8 +46,10 @@ include_HEADERS =    \
        silcargument.h  \
        silcstatus.h    \
        silcattrs.h
-endif
 
-EXTRA_DIST = *.h tests
+SILC_EXTRA_DIST = tests
+#endif SILC_DIST_TOOLKIT
+
+EXTRA_DIST = *.h $(SILC_EXTRA_DIST)
 
 include $(top_srcdir)/Makefile.defines.in
index b0d8382a55b45d71d8c54d7652b9e81f02ad827e..50da74b6ba68aaebeef2b62168a85047003af56d 100644 (file)
@@ -159,6 +159,7 @@ SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload);
  * SYNOPSIS
  *
  *    unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
+ *                                               SilcUInt32 *type,
  *                                               SilcUInt32 *ret_len);
  *
  * DESCRIPTION
index 7af8f6a052ed5068ee121ee5c3577e6d34b1edd5..b01bfec7be2ca4fd9ae257464243051196284ee6 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcattrs.c 
+  silcattrs.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -93,7 +93,7 @@ silc_attribute_payload_encode_int(SilcAttribute attribute,
     case SILC_ATTRIBUTE_STATUS_MOOD:
     case SILC_ATTRIBUTE_PREFERRED_CONTACT:
       {
-       SilcUInt32 mask = (SilcUInt32)object;
+       SilcUInt32 mask = SILC_PTR_TO_32(object);
        if (object_size != sizeof(SilcUInt32))
          return NULL;
        SILC_PUT32_MSB(mask, tmp);
@@ -293,7 +293,7 @@ SilcDList silc_attribute_payload_parse(const unsigned char *payload,
     ret = silc_buffer_unformat(&buffer,
                               SILC_STR_UI_CHAR(&newp->attribute),
                               SILC_STR_UI_CHAR(&newp->flags),
-                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data, 
+                              SILC_STR_UI16_NSTRING_ALLOC(&newp->data,
                                                           &newp->data_len),
                               SILC_STR_END);
     if (ret == -1)
@@ -311,7 +311,7 @@ SilcDList silc_attribute_payload_parse(const unsigned char *payload,
 
     silc_dlist_add(list, newp);
   }
-  
+
   return list;
 
  err:
@@ -354,7 +354,7 @@ SilcBuffer silc_attribute_payload_encode_data(SilcBuffer attrs,
     return NULL;
   silc_buffer_pull(buffer, buffer->len);
   silc_buffer_pull_tail(buffer, len);
-  silc_buffer_format(buffer, 
+  silc_buffer_format(buffer,
                     SILC_STR_UI_CHAR(attribute),
                     SILC_STR_UI_CHAR(flags),
                     SILC_STR_UI_SHORT((SilcUInt16)data_len),
@@ -444,7 +444,7 @@ unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
       if (!data)
        return NULL;
       silc_buffer_set(&buffer, data + len, 4 + attr->data_len);
-      silc_buffer_format(&buffer, 
+      silc_buffer_format(&buffer,
                         SILC_STR_UI_CHAR(attr->attribute),
                         SILC_STR_UI_CHAR(attr->flags),
                         SILC_STR_UI_SHORT(attr->data_len),
index afcc019405b55bd3dac9492718a921c380ad1ed4..2c578dbfda27d67cad736ebd8ed93a630cdaea8a 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcattrs.h 
+  silcattrs.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@
 /****s* silccore/SilcAttributesAPI/SilcAttributePayload
  *
  * NAME
- * 
+ *
  *    typedef struct SilcAttributePayloadStruct *SilcAttributePayload;
  *
  * DESCRIPTION
@@ -49,7 +49,7 @@ typedef struct SilcAttributePayloadStruct *SilcAttributePayload;
 /****d* silccore/SilcAttributesAPI/SilcAttribute
  *
  * NAME
- * 
+ *
  *    typedef SilcUInt8 SilcAttribute;
  *
  * DESCRIPTION
@@ -90,7 +90,7 @@ typedef SilcUInt8 SilcAttribute;
 /****d* silccore/SilcAttributesAPI/SilcAttributeFlags
  *
  * NAME
- * 
+ *
  *    typedef SilcUInt8 SilcAttributeFlags;
  *
  * DESCRIPTION
@@ -110,7 +110,7 @@ typedef SilcUInt8 SilcAttributeFlags;
 /****d* silccore/SilcAttributesAPI/SilcAttributeMood
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcAttributeMood;
  *
  * DESCRIPTION
@@ -139,7 +139,7 @@ typedef enum {
 /****d* silccore/SilcAttributesAPI/SilcAttributeContact
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcAttributeContact;
  *
  * DESCRIPTION
@@ -157,13 +157,14 @@ typedef enum {
   SILC_ATTRIBUTE_CONTACT_SMS     = 0x00000008,   /* SMS preferred */
   SILC_ATTRIBUTE_CONTACT_MMS     = 0x00000010,   /* MMS preferred */
   SILC_ATTRIBUTE_CONTACT_CHAT    = 0x00000020,   /* chatting preferred */
+  SILC_ATTRIBUTE_CONTACT_VIDEO   = 0x00000040,   /* video conferencing */
 } SilcAttributeContact;
 /***/
 
 /****d* silccore/SilcAttributesAPI/SilcAttributeDevice
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcAttributeDevice;
  *
  * DESCRIPTION
@@ -379,7 +380,7 @@ unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
 /****s* silccore/SilcAttributesAPI/SilcAttributeObjService
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } SilcAttributeObjService;
  *
  * DESCRIPTION
@@ -388,7 +389,7 @@ unsigned char *silc_attribute_get_verify_data(SilcDList attrs,
  *
  * SOURCE
  */
-typedef struct {
+typedef struct SilcAttributeObjServiceStruct {
   SilcUInt32 port;             /* IANA specified service port */
   SilcUInt32 idle;             /* Idle time in the service */
   char signon[64];             /* Signon date and time (UTC) */
@@ -400,7 +401,7 @@ typedef struct {
 /****s* silccore/SilcAttributesAPI/SilcAttributeObjMime
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } SilcAttributeObjMime;
  *
  * DESCRIPTION
@@ -410,7 +411,7 @@ typedef struct {
  *
  * SOURCE
  */
-typedef struct {
+typedef struct SilcAttributeObjMimeStruct {
   const unsigned char *mime;   /* MIME buffer */
   SilcUInt32 mime_len;         /* length of the MIME buffer */
 } SilcAttributeObjMime;
@@ -419,7 +420,7 @@ typedef struct {
 /****s* silccore/SilcAttributesAPI/SilcAttributeObjGeo
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } SilcAttributeObjGeo;
  *
  * DESCRIPTION
@@ -429,7 +430,7 @@ typedef struct {
  *
  * SOURCE
  */
-typedef struct {
+typedef struct SilcAttributeObjGeoStruct {
   char *longitude;             /* Longitude */
   char *latitude;              /* Latitude */
   char *altitude;              /* Altitude */
@@ -440,7 +441,7 @@ typedef struct {
 /****s* silccore/SilcAttributesAPI/SilcAttributeObjDevice
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } SilcAttributeObjDevice;
  *
  * DESCRIPTION
@@ -450,7 +451,7 @@ typedef struct {
  *
  * SOURCE
  */
-typedef struct {
+typedef struct SilcAttributeObjDeviceStruct {
   SilcAttributeDevice type;    /* device type */
   char *manufacturer;          /* manufacturer of the device */
   char *version;               /* device version string */
@@ -462,17 +463,30 @@ typedef struct {
 /****s* silccore/SilcAttributesAPI/SilcAttributeObjPk
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } SilcAttributeObjPk;
  *
  * DESCRIPTION
  *
  *    Data type for public key, certificate or digital signatures.  The
- *    caller must free the data inside the structure.
+ *    caller must free the data inside the structure.  The 'type' is one
+ *    of following: "silc-rsa", "silc-dss, "ssh-rsa", "ssh-dss",
+ *    "pgp-sign-rsa", "pgp-sign-dss", "x509v3-sign-rsa", "x509v3-sign-dss".
+ *    See the draft-riikonen-precense-attrs draft for more detailed
+ *    information.  The 'type' is NULL when this structure includes a
+ *    digital signature.
+ *
+ *    In SILC, at least the "silc-rsa" must be supported.  In this case
+ *    the key is normal SILC Public key.  To verify a signature with the
+ *    SILC Public key, construct the signature data with the
+ *    silc_attribute_get_verify_data and verify the signature with
+ *    for example silc_pkcs_verify_with_hash function.  The public key
+ *    to the verification is the `data' and `data_len', and can be decoded
+ *    with silc_pkcs_public_key_decode function.
  *
  * SOURCE
  */
-typedef struct {
+typedef struct SilcAttributeObjPkStruct {
   char *type;                  /* public key/certificate type, NULL
                                   when contains digital signature. */
   unsigned char *data;         /* public key/cert/signature data. The
@@ -502,6 +516,17 @@ typedef struct {
  *    You can use silc_attribute_get_attribute to get the SilcAttribute
  *    type from the `payload'.
  *
+ * EXAMPLE
+ *
+ *    SilcAttributeObjDevice dev;
+ *
+ *    ...
+ *    case SILC_ATTRIBUTE_DEVICE_INFO:
+ *    memset(&dev, 0, sizeof(dev));
+ *    if (!silc_attribute_get_object(payload, (void *)&dev, sizeof(dev)))
+ *      error();
+ *    ...
+ *
  ***/
 bool silc_attribute_get_object(SilcAttributePayload payload,
                               void *object, SilcUInt32 object_size);
index a16dfc6fce792b6e0c8edfe1ac0d17265120b219..7a3eeb1c75da9b79ebff95e1cc404daadd191a9d 100644 (file)
@@ -64,12 +64,13 @@ SilcCommandPayload silc_command_payload_parse(const unsigned char *payload,
                             SILC_STR_UI_SHORT(&newp->ident),
                             SILC_STR_END);
   if (ret == -1) {
+    SILC_LOG_ERROR(("Incorrect command payload in packet"));
     silc_free(newp);
     return NULL;
   }
 
   if (p_len != buffer.len) {
-    SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
+    SILC_LOG_ERROR(("Incorrect command payload in packet"));
     silc_free(newp);
     return NULL;
   }
index fb284c22237fc333807f9a90b56e4deb264e6d67..da86f7437a5cc51409c6662ebd4c9772b6ec371b 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+  Copyright (C) 2000 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -68,6 +68,8 @@ struct SilcIDCacheStruct {
   SilcHashTable context_table;
   SilcIDCacheDestructor destructor;
   SilcIdType type;
+  unsigned int delete_id : 1;
+  unsigned int delete_name : 1;
 };
 
 /*
@@ -99,7 +101,8 @@ struct SilcIDCacheListStruct {
    cache. */
 
 SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type,
-                              SilcIDCacheDestructor destructor)
+                              SilcIDCacheDestructor destructor,
+                              bool delete_id, bool delete_name)
 {
   SilcIDCache cache;
 
@@ -109,17 +112,20 @@ SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type,
   if (!cache)
     return NULL;
   cache->id_table = silc_hash_table_alloc(count, silc_hash_id,
-                                         (void *)(SilcUInt32)id_type,
+                                         SILC_32_TO_PTR(id_type),
                                          silc_hash_id_compare,
-                                         (void *)(SilcUInt32)id_type,
-                                         silc_idcache_destructor, NULL, TRUE);
-  cache->name_table = silc_hash_table_alloc(count, silc_hash_string, NULL,
-                                           silc_hash_string_compare, NULL,
+                                         SILC_32_TO_PTR(id_type),
+                                         silc_idcache_destructor,
+                                         cache, TRUE);
+  cache->name_table = silc_hash_table_alloc(count, silc_hash_utf8_string, NULL,
+                                           silc_hash_utf8_compare, NULL,
                                            NULL, NULL, TRUE);
   cache->context_table = silc_hash_table_alloc(count, silc_hash_ptr, NULL,
                                               NULL, NULL, NULL, NULL, TRUE);
   cache->destructor = destructor;
   cache->type = id_type;
+  cache->delete_id = delete_id;
+  cache->delete_name = delete_name;
 
   if (!cache->id_table || !cache->name_table || !cache->context_table) {
     if (cache->id_table)
@@ -191,6 +197,13 @@ static void silc_idcache_destructor(void *key, void *context,
 {
   SilcIDCacheEntry c = context;
   if (c) {
+    SilcIDCache cache = user_context;
+    if (cache) {
+      if (cache->delete_id)
+       silc_free(c->id);
+      if (cache->delete_name)
+       silc_free(c->name);
+    }
     memset(c, 'F', sizeof(*c));
     silc_free(c);
   }
@@ -257,7 +270,6 @@ bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
     ret = silc_hash_table_del_ext(cache->id_table, c->id, hash,
                                  hash_context, compare, compare_context,
                                  NULL, NULL);
-
   return ret;
 }
 
index 71f8f445635bb152451898c4cdcdbb32a0338d8d..69c5290f1bdb8a639d2a74c0f56f6b8a9bbca88a 100644 (file)
@@ -1,16 +1,16 @@
 /*
+
   silcidcache.h
+
   Author: Pekka Riikonen <priikone@silcnet.org>
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+
+  Copyright (C) 2000 - 2005 Pekka Riikonen
+
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, 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
@@ -21,7 +21,7 @@
 /****h* silccore/SILC ID Cache Interface
  *
  * DESCRIPTION
- * 
+ *
  * SILC ID Cache is an cache for all kinds of ID's used in the SILC
  * protocol.  Application can save here the ID's it uses and the interface
  * provides fast retrieval of the ID's from the cache.
 /****s* silccore/SilcIDCacheAPI/SilcIDCacheEntry
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } SilcIDCacheEntry;
  *
  * DESCRIPTION
  *
  *    This is one entry in the SILC ID Cache system. Contents of this is
- *    allocated outside the ID cache system, however, all the fields are 
+ *    allocated outside the ID cache system, however, all the fields are
  *    filled with ID cache utility functions. The ID cache system does not
  *    allocate any of these fields nor free them.
  *
@@ -76,13 +76,13 @@ typedef struct {
 /****s* silccore/SilcIDCacheAPI/SilcIDCache
  *
  * NAME
- * 
+ *
  *    typedef struct SilcIDCacheStruct *SilcIDCache;
  *
  * DESCRIPTION
  *
- *    This context is the actual ID Cache and is allocated by 
- *    silc_idcache_alloc and given as argument usually to all 
+ *    This context is the actual ID Cache and is allocated by
+ *    silc_idcache_alloc and given as argument usually to all
  *    silc_idcache_* functions.  It is freed by the
  *    silc_idcache_free function.
  *
@@ -92,12 +92,12 @@ typedef struct SilcIDCacheStruct *SilcIDCache;
 /****s* silccore/SilcIDCacheAPI/SilcIDCacheList
  *
  * NAME
- * 
+ *
  *    typedef struct SilcIDCacheListStruct *SilcIDCacheList;
  *
  * DESCRIPTION
  *
- *    This context is the ID Cache List and is allocated by 
+ *    This context is the ID Cache List and is allocated by
  *    some of the silc_idcache_* functions. Functions that may return
  *    multiple entries from the cache allocate the entries in to the
  *    SilcIDCacheList. The context is freed by silc_idcache_list_free
@@ -139,13 +139,18 @@ typedef void (*SilcIDCacheDestructor)(SilcIDCache cache,
  * DESCRIPTION
  *
  *    Allocates new ID cache object. The initial amount of allocated entries
- *    can be sent as argument. If `count' is 0 the system uses default values. 
+ *    can be sent as argument. If `count' is 0 the system uses default values.
  *    The `id_type' defines the types of the ID's that will be saved to the
  *    cache.
  *
+ *    If 'delete_id' is TRUE then library will free the ID when a
+ *    cache entry is deleted.  If 'delete_name' is TRUE then library
+ *    will delete the associated name when a cache entry is deleted.
+ *
  ***/
 SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type,
-                              SilcIDCacheDestructor destructor);
+                              SilcIDCacheDestructor destructor,
+                              bool delete_id, bool delete_name);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_free
  *
@@ -164,7 +169,7 @@ void silc_idcache_free(SilcIDCache cache);
  *
  * SYNOPSIS
  *
- *    bool silc_idcache_add(SilcIDCache cache, char *name, void *id, 
+ *    bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
  *                          void *context, int expire, SilcIDCacheEntry *ret);
  *
  * DESCRIPTION
@@ -180,11 +185,11 @@ void silc_idcache_free(SilcIDCache cache);
  *    of deleting the cache entry.  Otherwise the cache will have the freed
  *    pointers stored.
  *
- *    If the `ret' is non-NULL the created ID Cache entry is returned to 
+ *    If the `ret' is non-NULL the created ID Cache entry is returned to
  *    that pointer.
  *
  ***/
-bool silc_idcache_add(SilcIDCache cache, char *name, void *id, 
+bool silc_idcache_add(SilcIDCache cache, char *name, void *id,
                      void *context, int expire, SilcIDCacheEntry *ret);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_del
@@ -220,9 +225,9 @@ bool silc_idcache_del_by_id(SilcIDCache cache, void *id);
  * SYNOPSIS
  *
  *    bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
- *                                    SilcHashFunction hash, 
+ *                                    SilcHashFunction hash,
  *                                    void *hash_context,
- *                                    SilcHashCompare compare, 
+ *                                    SilcHashCompare compare,
  *                                    void *compare_context);
  *
  * DESCRIPTION
@@ -230,13 +235,13 @@ bool silc_idcache_del_by_id(SilcIDCache cache, void *id);
  *    Same as silc_idcache_del_by_id but with specific hash and comparison
  *    functions. If the functions are NULL then default values are used.
  *    Returns TRUE if the entry was deleted. The destructor function is
- *    not called.
+ *    called.
  *
  ***/
 bool silc_idcache_del_by_id_ext(SilcIDCache cache, void *id,
-                               SilcHashFunction hash, 
+                               SilcHashFunction hash,
                                void *hash_context,
-                               SilcHashCompare compare, 
+                               SilcHashCompare compare,
                                void *compare_context);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_del_by_context
@@ -290,7 +295,7 @@ bool silc_idcache_purge(SilcIDCache cache);
  *
  * DESCRIPTION
  *
- *    Purges the cache by context and removes expired cache entires. 
+ *    Purges the cache by context and removes expired cache entires.
  *    Returns TRUE if the puring was successful. The destructor function
  *    is called for the purged cache entry.
  *
@@ -316,7 +321,7 @@ bool silc_idcache_get_all(SilcIDCache cache, SilcIDCacheList *ret);
  *
  * SYNOPSIS
  *
- *    bool silc_idcache_find_by_id(SilcIDCache cache, void *id, 
+ *    bool silc_idcache_find_by_id(SilcIDCache cache, void *id,
  *                                 SilcIDCacheList *ret);
  *
  * DESCRIPTION
@@ -326,14 +331,14 @@ bool silc_idcache_get_all(SilcIDCache cache, SilcIDCacheList *ret);
  *    found. The caller must free the returned SilcIDCacheList.
  *
  ***/
-bool silc_idcache_find_by_id(SilcIDCache cache, void *id, 
+bool silc_idcache_find_by_id(SilcIDCache cache, void *id,
                             SilcIDCacheList *ret);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_id_one
  *
  * SYNOPSIS
  *
- *     bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, 
+ *     bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
  *                                      SilcIDCacheEntry *ret);
  *
  * DESCRIPTION
@@ -343,17 +348,17 @@ bool silc_idcache_find_by_id(SilcIDCache cache, void *id,
  *    if the entry was found.
  *
  ***/
-bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id, 
+bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
                                 SilcIDCacheEntry *ret);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_id_one_ext
  *
  * SYNOPSIS
  *
- *    bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id, 
- *                                         SilcHashFunction hash, 
+ *    bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id,
+ *                                         SilcHashFunction hash,
  *                                         void *hash_context,
- *                                         SilcHashCompare compare, 
+ *                                         SilcHashCompare compare,
  *                                         void *compare_context,
  *                                         SilcIDCacheEntry *ret);
  *
@@ -365,10 +370,10 @@ bool silc_idcache_find_by_id_one(SilcIDCache cache, void *id,
  *    is used. Returns TRUE if the entry was found.
  *
  ***/
-bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id, 
-                                    SilcHashFunction hash, 
+bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id,
+                                    SilcHashFunction hash,
                                     void *hash_context,
-                                    SilcHashCompare compare, 
+                                    SilcHashCompare compare,
                                     void *compare_context,
                                     SilcIDCacheEntry *ret);
 
@@ -376,7 +381,7 @@ bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id,
  *
  * SYNOPSIS
  *
- *    bool silc_idcache_find_by_context(SilcIDCache cache, void *context, 
+ *    bool silc_idcache_find_by_context(SilcIDCache cache, void *context,
  *                                      SilcIDCacheEntry *ret);
  *
  * DESCRIPTION
@@ -385,14 +390,14 @@ bool silc_idcache_find_by_id_one_ext(SilcIDCache cache, void *id,
  *    entry was found.
  *
  ***/
-bool silc_idcache_find_by_context(SilcIDCache cache, void *context, 
+bool silc_idcache_find_by_context(SilcIDCache cache, void *context,
                                  SilcIDCacheEntry *ret);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_name
  *
  * SYNOPSIS
  *
- *    bool silc_idcache_find_by_name(SilcIDCache cache, char *name, 
+ *    bool silc_idcache_find_by_name(SilcIDCache cache, char *name,
  *                                   SilcIDCacheList *ret);
  *
  * DESCRIPTION
@@ -402,7 +407,7 @@ bool silc_idcache_find_by_context(SilcIDCache cache, void *context,
  *    TRUE if the entry was found. The caller must free the SIlcIDCacheList.
  *
  ***/
-bool silc_idcache_find_by_name(SilcIDCache cache, char *name, 
+bool silc_idcache_find_by_name(SilcIDCache cache, char *name,
                               SilcIDCacheList *ret);
 
 /****f* silccore/SilcIDCacheAPI/silc_idcache_find_by_name_one
@@ -440,7 +445,7 @@ int silc_idcache_list_count(SilcIDCacheList list);
  *
  * SYNOPSIS
  *
- *    bool silc_idcache_list_first(SilcIDCacheList list, 
+ *    bool silc_idcache_list_first(SilcIDCacheList list,
  *                                 SilcIDCacheEntry *ret);
  *
  * DESCRIPTION
index 8e1a9f81ec52dbc08e4ab6b86fdf6cfe8d0a11c8..ff139decbd61af9d43be8b9e33cec22ea6f8721c 100644 (file)
@@ -96,8 +96,9 @@ typedef SilcUInt16 SilcMessageFlags;
 #define SILC_MESSAGE_FLAG_REPLY       0x0040     /* A reply */
 #define SILC_MESSAGE_FLAG_DATA        0x0080     /* MIME object */
 #define SILC_MESSAGE_FLAG_UTF8        0x0100     /* UTF-8 string */
-#define SILC_MESSAGE_FLAG_RESERVED    0x0200     /* to 0x0800 */
-#define SILC_MESSAGE_FLAG_PRIVATE     0x1000     /* to 0x8000 */
+#define SILC_MESSAGE_FLAG_ACK         0x0200     /* ACK messages */
+#define SILC_MESSAGE_FLAG_RESERVED    0x0400     /* to 0x1000 */
+#define SILC_MESSAGE_FLAG_PRIVATE     0x2000     /* to 0x8000 */
 /***/
 
 /****f* silccore/SilcMessageAPI/silc_message_payload_decrypt
@@ -455,7 +456,9 @@ int silc_message_signed_verify(SilcMessageSignedPayload sig,
  * SYNOPSIS
  *
  *    SilcPublicKey
- *    silc_message_signed_get_public_key(SilcMessageSignedPayload sig);
+ *    silc_message_signed_get_public_key(SilcMessageSignedPayload sig,
+ *                                       unsigned char **pk_data,
+ *                                       SilcUInt32 *pk_data_len);
  *
  * DESCRIPTION
  *
index 167d7d17a61fcae170a8cf4b8171344b9d6a447a..a9ce5639d33f2546a140e67fe25a573f1592e5c3 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -56,8 +56,12 @@ int silc_packet_send(SilcSocketConnection sock, bool force_send)
     ret = silc_socket_write(sock);
 
     if (ret == -1) {
-      SILC_LOG_ERROR(("Error sending packet, dropped: %s",
-                      strerror(errno)));
+      SILC_LOG_ERROR(("Error sending packet to %s:%d [%s], dropped: %s",
+                     sock->hostname ? sock->hostname : "", sock->port,
+                     (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
+                      sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
+                      sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
+                      "Router"), strerror(errno)));
     }
     if (ret != -2)
       return ret;
@@ -323,10 +327,12 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     mac_len = silc_hmac_len(hmac);
 
   /* Parse the packets from the data */
+  silc_socket_dup(sock);
   while (sock->inbuf->len > 0 && cont) {
 
     if (sock->inbuf->len < SILC_PACKET_MIN_HEADER_LEN) {
       SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
+      silc_socket_free(sock);
       return TRUE;
     }
 
@@ -349,6 +355,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
       SILC_LOG_ERROR(("Received too short packet"));
       memset(header, 0, sizeof(header));
       silc_buffer_clear(sock->inbuf);
+      silc_socket_free(sock);
       return FALSE;
     }
 
@@ -357,6 +364,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
                      "(%d bytes)", paddedlen + mac_len - sock->inbuf->len));
       SILC_SET_INBUF_PENDING(sock);
       memset(tmp, 0, sizeof(tmp));
+      silc_socket_free(sock);
       return TRUE;
     }
 
@@ -364,23 +372,27 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     if (!silc_packet_check_mac(hmac, sock->inbuf->data, paddedlen,
                               sock->inbuf->data + paddedlen, sequence)) {
       SILC_LOG_WARNING(("Packet MAC check failed %s:%d "
-                       "[%s type %d len %dB seq %d] [%s]",
+                       "[%s type %d len %dB blen %dB seq %d] [%s] proto %d",
                        sock->hostname, sock->port,
                        silc_get_packet_name(header[3]),
-                       header[3], paddedlen, sequence,
+                       header[3], paddedlen, sock->inbuf->len, sequence,
                        (sock->type == SILC_SOCKET_TYPE_UNKNOWN ? "Unknown" :
                         sock->type == SILC_SOCKET_TYPE_CLIENT ? "Client" :
                         sock->type == SILC_SOCKET_TYPE_SERVER ? "Server" :
-                        "Router")));
+                        "Router"),
+                       sock->protocol ? sock->protocol->protocol->type : -1));
       memset(tmp, 0, sizeof(tmp));
       silc_buffer_clear(sock->inbuf);
+      silc_socket_free(sock);
       return FALSE;
     }
 
     SILC_UNSET_INBUF_PENDING(sock);
     parse_ctx = silc_calloc(1, sizeof(*parse_ctx));
-    if (!parse_ctx)
+    if (!parse_ctx) {
+      silc_socket_free(sock);
       return FALSE;
+    }
     parse_ctx->packet = silc_packet_context_alloc();
     parse_ctx->packet->buffer = silc_buffer_alloc_size(paddedlen);
     parse_ctx->packet->type = (SilcPacketType)header[3];
@@ -431,6 +443,7 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
        memset(tmp, 0, sizeof(tmp));
        silc_packet_context_free(parse_ctx->packet);
        silc_free(parse_ctx);
+       silc_socket_free(sock);
        return FALSE;
       }
     }
@@ -457,11 +470,21 @@ bool silc_packet_receive_process(SilcSocketConnection sock,
     memset(tmp, 0, sizeof(tmp));
   }
 
-  if (cont == FALSE && sock->inbuf->len > 0)
+  /* Don't clear buffer if pending data is in the buffer */
+  if (cont == FALSE && sock->inbuf->len > 0) {
+    silc_socket_free(sock);
     return TRUE;
+  }
+
+  /* Don't clear buffer if QoS data exists in the buffer */
+  if (sock->qos && sock->qos->data_len > 0) {
+    silc_socket_free(sock);
+    return TRUE;
+  }
 
   SILC_LOG_DEBUG(("Clearing inbound buffer"));
   silc_buffer_clear(sock->inbuf);
+  silc_socket_free(sock);
   return TRUE;
 }
 
index 3b5c7cd0ec648fd97cee67c6fbfd0cfada70ec17..3f1637b6f07db4e78597fc009ae374f5b4a49abd 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 - 2003 Pekka Riikonen
+  Copyright (C) 2002 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -102,6 +102,8 @@ typedef SilcUInt8 SilcStatus;
 #define SILC_STATUS_ERR_TIMEDOUT            54
 #define SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY    55
 #define SILC_STATUS_ERR_OPERATION_ALLOWED   56
+#define SILC_STATUS_ERR_BAD_SERVER          57
+#define SILC_STATUS_ERR_BAD_USERNAME        58
 /***/
 
 #define SILC_STATUS_IS_ERROR(status) (status >= SILC_STATUS_ERR_NO_SUCH_NICK)
index c585952f75d23af04ebdc741f59953a020c5d048..6c7c743205336bde1cca4d360c05a4cd09279e64 100644 (file)
@@ -5,6 +5,7 @@
 @LINK=silcrng.html:SILC RNG Interface
 @LINK=silccipher.html:SILC Cipher API
 @LINK=silcpkcs.html:SILC PKCS API
+@LINK=silcpkcs1.html:SILC PKCS#1 API
 @LINK=silchash.html:SILC Hash Interface
 @LINK=silchmac.html:SILC HMAC Interface
 -->
@@ -25,4 +26,3 @@ strong random number generator.
 
 <br /><br />
 @LINKS@
-
similarity index 81%
rename from lib/silccrypt/Makefile.am
rename to lib/silccrypt/Makefile.ad
index 3dd281ca453b60687de3d847b636417272633bcf..c5b3a112bcf1391a79a03c5fd5e1cb0cc92e7e86 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -23,7 +22,6 @@ noinst_LTLIBRARIES = libsilccrypt.la
 libsilccrypt_la_SOURCES = \
        none.c \
        rc5.c \
-       rc6.c \
        md5.c \
        aes.c \
        rsa.c \
@@ -36,18 +34,18 @@ libsilccrypt_la_SOURCES = \
        silchmac.c \
        silcrng.c \
        silcpkcs.c \
-       pkcs1.c
+       silcpkcs1.c
 
 if SILC_LIBTOOLFIX
 # Tell libtool to compile silccrypt as shared since silcsim will need it.
 LTFLAGS = --libtool-enable-shared
 else
-LTFLAGS = 
+LTFLAGS =
 endif
 
 CFLAGS = $(LTFLAGS)
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS =      \
        aes.h           \
        blowfish.h      \
@@ -56,9 +54,7 @@ include_HEADERS =     \
        ciphers.h       \
        md5.h           \
        none.h          \
-       pkcs1.h         \
        rc5.h           \
-       rc6.h           \
        rsa.h           \
        sha1.h          \
        silccipher.h    \
@@ -67,10 +63,13 @@ include_HEADERS =   \
        silchmac.h      \
        silcpkcs.h      \
        silcrng.h       \
+       silcpkcs1.h     \
        twofish.h
-endif
 
-EXTRA_DIST = *.h tests
+SILC_EXTRA_DIST = tests
+#endif SILC_DIST_TOOLKIT
+
+EXTRA_DIST = *.h $(SILC_EXTRA_DIST)
 
 include $(top_srcdir)/Makefile.defines.in
 
index 2eb7edfcaafddeff1d793ff493b2055c49ca3585..94eeef68f9f79058f87c33c2fa92d4317116468c 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "none.h"
 #include "rc5.h"
-#include "rc6.h"
 #include "twofish.h"
 #include "aes.h"
 #include "blowfish.h"
diff --git a/lib/silccrypt/pkcs1.c b/lib/silccrypt/pkcs1.c
deleted file mode 100644 (file)
index 9896373..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-/* $Id$ */
-/* 
-   PKCS #1 RSA wrapper.
-
-   Heavily modified to work under SILC, rewrote all interfaces, code that
-   is not needed in SILC has been removed for good, and some code was fixed
-   and changed.
-
-   For example, RSA_DecodeOneBlock was not used at all by Mozilla, however,
-   I took this code in to use after doing some fixing (it had some bugs).  
-   Also, OAEP is removed totally for now.  I'm not sure whether OAEP could
-   be used in the future with SILC but not for now.
-
-   This file also implements partial SILC PKCS API for RSA with PKCS #1.
-   It is partial because all the other functions but encrypt, decrypt,
-   sign and verify are common.
-
-   Note:
-
-   The mandatory PKCS #1 implementation in SILC must be compliant to either
-   PKCS #1 version 1.5 or PKCS #1 version 2 with the following notes:
-   The signature encoding is always in same format as the encryption
-   encoding regardles of the PKCS #1 version.  The signature with
-   appendix (with hash algorithm OID in the data) must not be used
-   in the SILC.  Rationale for this is that there is no binding between
-   the PKCS #1 OIDs and the hash algorithms used in the SILC protocol.
-   Hence, the encoding is always in PKCS #1 version 1.5 format.
-
-   Any questions and comments regarding this modified version should be
-   sent to priikone@silcnet.org.
-
-   References: ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1v2.asc,
-               ftp://ftp.rsasecurity.com/pub/pkcs/ascii/pkcs-1.asc,
-              and RFC 2437.
-
-   Copyright notice: All code in this file, including the SILC PKCS API
-   code that is not part of the Mozilla code, falls under the same license
-   (MPL or GPL) found attached to this file, below.
-*/
-
-/*
- * PKCS#1 encoding and decoding functions.
- * This file is believed to contain no code licensed from other parties.
- *
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- * 
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- * 
- * The Original Code is the Netscape security libraries.
- * 
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation.  Portions created by Netscape are 
- * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
- * Rights Reserved.
- * 
- * Contributor(s):
- * 
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable 
- * instead of those above.  If you wish to allow use of your 
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL.  If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- *
- * $Id$
- */
-
-#include "silcincludes.h"
-#include "rsa_internal.h"
-#include "rsa.h"
-
-#define RSA_BLOCK_MIN_PAD_LEN          8
-#define RSA_BLOCK_FIRST_OCTET          0x00
-#define RSA_BLOCK_PRIVATE0_PAD_OCTET   0x00
-#define RSA_BLOCK_PRIVATE_PAD_OCTET    0xff
-#define RSA_BLOCK_AFTER_PAD_OCTET      0x00
-
-/*
- * RSA block types
- *
- * The actual values are important -- they are fixed, *not* arbitrary.
- * The explicit value assignments are not needed (because C would give
- * us those same values anyway) but are included as a reminder...
- */
-typedef enum {
-    RSA_BlockPrivate0 = 0,     /* unused, really */
-    RSA_BlockPrivate = 1,      /* pad for a private-key operation */
-    RSA_BlockPublic = 2,       /* pad for a public-key operation */
-    RSA_BlockTotal
-} RSA_BlockType;
-
-/*
- * Format one block of data for public/private key encryption using
- * the rules defined in PKCS #1.
- */
-static unsigned char *
-RSA_FormatOneBlock(SilcUInt32 modulusLen, RSA_BlockType blockType,
-                  unsigned char *data, SilcUInt32 data_len)
-{
-    unsigned char *block;
-    unsigned char *bp;
-    int padLen;
-    int i;
-
-    block = (unsigned char *) silc_malloc(modulusLen);
-    if (block == NULL)
-       return NULL;
-
-    bp = block;
-
-    /*
-     * All RSA blocks start with two octets:
-     * 0x00 || BlockType
-     */
-    *bp++ = RSA_BLOCK_FIRST_OCTET;
-    *bp++ = (unsigned char) blockType;
-
-    switch (blockType) {
-
-      /*
-       * Blocks intended for private-key operation.
-       */
-      case RSA_BlockPrivate0: /* essentially unused */
-      case RSA_BlockPrivate:    /* preferred method */
-       /*
-        * 0x00 || BT || Pad || 0x00 || ActualData
-        *   1      1   padLen    1      data_len
-        * Pad is either all 0x00 or all 0xff bytes, depending on blockType.
-        */
-       padLen = modulusLen - data_len - 3;
-       assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
-       memset(bp,
-                  blockType == RSA_BlockPrivate0
-                       ? RSA_BLOCK_PRIVATE0_PAD_OCTET
-                       : RSA_BLOCK_PRIVATE_PAD_OCTET,
-                  padLen);
-       bp += padLen;
-       *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
-       memcpy(bp, data, data_len);
-       break;
-
-      /*
-       * Blocks intended for public-key operation.
-       */
-      case RSA_BlockPublic:
-       /*
-        * 0x00 || BT || Pad || 0x00 || ActualData
-        *   1      1   padLen    1      data_len
-        * Pad is all non-zero random bytes.
-        */
-       padLen = modulusLen - data_len - 3;
-       assert(padLen >= RSA_BLOCK_MIN_PAD_LEN);
-       for (i = 0; i < padLen; i++) {
-           /* Pad with non-zero random data. */
-           do {
-             bp[i] = silc_rng_global_get_byte();
-           } while (bp[i] == RSA_BLOCK_AFTER_PAD_OCTET);
-       }
-       bp += padLen;
-       *bp++ = RSA_BLOCK_AFTER_PAD_OCTET;
-       memcpy(bp, data, data_len);
-       break;
-
-      default:
-       silc_free(block);
-       return NULL;
-    }
-
-    return block;
-}
-
-static int
-RSA_FormatBlock(unsigned char **result, SilcUInt32 *result_len,
-               SilcUInt32 modulusLen,
-               RSA_BlockType blockType, unsigned char *data,
-               SilcUInt32 data_len)
-{
-    /*
-     * XXX For now assume that the data length fits in a single
-     * XXX encryption block; the ASSERTs below force this.
-     * XXX To fix it, each case will have to loop over chunks whose
-     * XXX lengths satisfy the assertions, until all data is handled.
-     * XXX (Unless RSA has more to say about how to handle data
-     * XXX which does not fit in a single encryption block?)
-     * XXX And I do not know what the result is supposed to be,
-     * XXX so the interface to this function may need to change
-     * XXX to allow for returning multiple blocks, if they are
-     * XXX not wanted simply concatenated one after the other.
-     */
-
-    switch (blockType) {
-      case RSA_BlockPrivate0:
-      case RSA_BlockPrivate:
-      case RSA_BlockPublic:
-       /*
-        * 0x00 || BT || Pad || 0x00 || ActualData
-        *
-        * The "3" below is the first octet + the second octet + the 0x00
-        * octet that always comes just before the ActualData.
-        */
-       assert(data_len <= (modulusLen - (3 + RSA_BLOCK_MIN_PAD_LEN)));
-
-       *result = RSA_FormatOneBlock(modulusLen, blockType, data, data_len);
-       if (result == NULL) {
-           *result_len = 0;
-           return FALSE;
-       }
-       *result_len = modulusLen;
-
-       break;
-
-      default:
-       *result = NULL;
-       *result_len = 0;
-       return FALSE;
-    }
-
-    return TRUE;
-}
-
-/*
- * Takes a formatted block and returns the data part.
- * (This is the inverse of RSA_FormatOneBlock().)
- * In some formats the start of the data is ambiguous;
- * if it is non-zero, expectedLen will disambiguate.
- *
- */
-unsigned char *
-RSA_DecodeOneBlock(unsigned char *data,
-                  SilcUInt32 modulusLen,
-                  SilcUInt32 expectedLen,
-                  RSA_BlockType bt,
-                  SilcUInt32 *pResultLen)
-{
-    RSA_BlockType blockType;
-    unsigned char *dp, *res;
-    SilcUInt32 i, len = 0;
-
-    dp = data;
-    if (dp[0] != RSA_BLOCK_FIRST_OCTET) {
-       return NULL;
-    }
-
-    blockType = (RSA_BlockType)dp[1];
-    if (blockType != bt)
-      return NULL;
-
-    if (modulusLen < 2 + 1)
-      return NULL;
-
-    dp += 2;
-
-    switch (blockType) {
-      case RSA_BlockPrivate0:
-       /* Ignored */
-       res = (unsigned char *) silc_malloc(modulusLen);
-       memcpy(res, data, modulusLen);
-       break;
-
-      case RSA_BlockPrivate:
-       for (i = 0; i < modulusLen; i++) {
-           if (*dp++ != RSA_BLOCK_PRIVATE_PAD_OCTET)
-               break;
-       }
-       if (i == modulusLen)
-           return NULL;
-       len = modulusLen - (dp - data);
-       res = (unsigned char *) silc_malloc(len);
-       if (res == NULL) {
-           return NULL;
-       }
-       memcpy(res, dp, len);
-       break;
-
-      case RSA_BlockPublic:
-       for (i = 0; i < modulusLen; i++) {
-           if (*dp++ == RSA_BLOCK_AFTER_PAD_OCTET)
-               break;
-       }
-       if (i == modulusLen)
-           return NULL;
-       len = modulusLen - (dp - data);
-       res = (unsigned char *) silc_malloc(len);
-       if (res == NULL) {
-           return NULL;
-       }
-       memcpy(res, dp, len);
-       break;
-
-      default:
-       return NULL;
-    }
-
-    if (pResultLen)
-      *pResultLen = len;
-    return res;
-}
-
-/*
- * SILC PKCS API for PKCS #1
- *
- * Note all the other PKCS API functions are used from the rsa.c.
- * See the definitions in rsa.c and in silcpkcs.c.
- */
-
-SILC_PKCS_API_ENCRYPT(pkcs1)
-{
-  RsaKey *key = (RsaKey *)context;
-  SilcMPInt mp_tmp;
-  SilcMPInt mp_dst;
-  unsigned char *padded;
-  SilcUInt32 padded_len, len = (key->bits + 7) / 8;
-
-  /* Pad data */
-  if (!RSA_FormatBlock(&padded, &padded_len, len,
-                      RSA_BlockPublic, src, src_len))
-    return FALSE;
-
-  silc_mp_init(&mp_tmp);
-  silc_mp_init(&mp_dst);
-
-  /* Data to MP */
-  silc_mp_bin2mp(padded, padded_len, &mp_tmp);
-
-  /* Encrypt */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
-  
-  /* MP to data */
-  silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
-  *dst_len = len;
-
-  memset(padded, 0, padded_len);
-  silc_free(padded);
-  silc_mp_uninit(&mp_tmp);
-  silc_mp_uninit(&mp_dst);
-
-  return TRUE;
-}
-
-SILC_PKCS_API_DECRYPT(pkcs1)
-{
-  RsaKey *key = (RsaKey *)context;
-  SilcMPInt mp_tmp;
-  SilcMPInt mp_dst;
-  unsigned char *padded, *unpadded;
-  SilcUInt32 padded_len;
-
-  silc_mp_init(&mp_tmp);
-  silc_mp_init(&mp_dst);
-
-  /* Data to MP */
-  silc_mp_bin2mp(src, src_len, &mp_tmp);
-
-  /* Decrypt */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
-
-  /* MP to data */
-  padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
-
-  /* Unpad data */
-  unpadded = RSA_DecodeOneBlock(padded, padded_len, 0, 
-                               RSA_BlockPublic, &padded_len);
-  if (!unpadded) {
-    memset(padded, 0, padded_len);
-    silc_free(padded);
-    silc_mp_uninit(&mp_tmp);
-    silc_mp_uninit(&mp_dst);
-    return FALSE;
-  }
-
-  /* Copy to destination */
-  memcpy(dst, unpadded, padded_len);
-  *dst_len = padded_len;
-
-  memset(padded, 0, padded_len);
-  memset(unpadded, 0, padded_len);
-  silc_free(padded);
-  silc_free(unpadded);
-  silc_mp_uninit(&mp_tmp);
-  silc_mp_uninit(&mp_dst);
-
-  return TRUE;
-}
-
-SILC_PKCS_API_SIGN(pkcs1)
-{
-  RsaKey *key = (RsaKey *)context;
-  SilcMPInt mp_tmp;
-  SilcMPInt mp_dst;
-  unsigned char *padded;
-  SilcUInt32 padded_len;
-  SilcUInt32 len = (key->bits + 7) / 8;
-
-  /* Pad data */
-  if (!RSA_FormatBlock(&padded, &padded_len, len, RSA_BlockPrivate, 
-                      src, src_len))
-    return FALSE;
-
-  silc_mp_init(&mp_tmp);
-  silc_mp_init(&mp_dst);
-
-  /* Data to MP */
-  silc_mp_bin2mp(padded, len, &mp_tmp);
-
-  /* Sign */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
-  
-  /* MP to data */
-  silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
-  *dst_len = len;
-
-  memset(padded, 0, padded_len);
-  silc_free(padded);
-  silc_mp_uninit(&mp_tmp);
-  silc_mp_uninit(&mp_dst);
-
-  return TRUE;
-}
-
-SILC_PKCS_API_VERIFY(pkcs1)
-{
-  RsaKey *key = (RsaKey *)context;
-  int ret = TRUE;
-  SilcMPInt mp_tmp2;
-  SilcMPInt mp_dst;
-  unsigned char *verify, *unpadded;
-  SilcUInt32 verify_len, len = (key->bits + 7) / 8;
-
-  silc_mp_init(&mp_tmp2);
-  silc_mp_init(&mp_dst);
-
-  /* Format the signature into MP int */
-  silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
-
-  /* Verify */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
-
-  /* MP to data */
-  verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
-
-  /* Unpad data */
-  unpadded = RSA_DecodeOneBlock(verify, len, 0, 
-                               RSA_BlockPrivate, &verify_len);
-  if (!unpadded) {
-    memset(verify, 0, verify_len);
-    silc_free(verify);
-    silc_mp_uninit(&mp_tmp2);
-    silc_mp_uninit(&mp_dst);
-    return FALSE;
-  }
-
-  /* Compare */
-  if (memcmp(data, unpadded, verify_len))
-    ret = FALSE;
-
-  memset(verify, 0, verify_len);
-  memset(unpadded, 0, verify_len);
-  silc_free(verify);
-  silc_free(unpadded);
-  silc_mp_uninit(&mp_tmp2);
-  silc_mp_uninit(&mp_dst);
-
-  return ret;
-}
diff --git a/lib/silccrypt/pkcs1.h b/lib/silccrypt/pkcs1.h
deleted file mode 100644 (file)
index 38937ae..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-
-  pkcs1.h
-
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
-
-  Copyright (C) 2001 Pekka Riikonen
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
-
-*/
-#ifndef PKCS1_H
-#define PKCS1_H
-
-/*
- * SILC PKCS API for PKCS #1
- *
- * Note all the other PKCS API functions are used from the rsa.c.
- * See the definitions in rsa.c and in silcpkcs.c.
- */
-
-SILC_PKCS_API_ENCRYPT(pkcs1);
-SILC_PKCS_API_DECRYPT(pkcs1);
-SILC_PKCS_API_SIGN(pkcs1);
-SILC_PKCS_API_VERIFY(pkcs1);
-
-#endif
diff --git a/lib/silccrypt/rc6.c b/lib/silccrypt/rc6.c
deleted file mode 100644 (file)
index 2ca7c83..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/* Modified for SILC. -Pekka */
-
-/* This is an independent implementation of the encryption algorithm:   */
-/*                                                                      */
-/*         RC6 by Ron Rivest and RSA Labs                               */
-/*                                                                      */
-/* which is a candidate algorithm in the Advanced Encryption Standard   */
-/* programme of the US National Institute of Standards and Technology.  */
-/*                                                                      */
-/* Copyright in this implementation is held by Dr B R Gladman but I     */
-/* hereby give permission for its free direct or derivative use subject */
-/* to acknowledgment of its origin and compliance with any conditions   */
-/* that the originators of the algorithm place on its exploitation.     */
-/*                                                                      */
-/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999     */
-
-/* Timing data for RC6 (rc6.c)
-
-128 bit key:
-Key Setup:    1632 cycles
-Encrypt:       270 cycles =    94.8 mbits/sec
-Decrypt:       226 cycles =   113.3 mbits/sec
-Mean:          248 cycles =   103.2 mbits/sec
-
-192 bit key:
-Key Setup:    1885 cycles
-Encrypt:       267 cycles =    95.9 mbits/sec
-Decrypt:       235 cycles =   108.9 mbits/sec
-Mean:          251 cycles =   102.0 mbits/sec
-
-256 bit key:
-Key Setup:    1877 cycles
-Encrypt:       270 cycles =    94.8 mbits/sec
-Decrypt:       227 cycles =   112.8 mbits/sec
-Mean:          249 cycles =   103.0 mbits/sec
-
-*/
-
-#include "silcincludes.h"
-#include "rc6_internal.h"
-#include "rc6.h"
-
-/* 
- * SILC Crypto API for RC6
- */
-
-/* Sets the key for the cipher. */
-
-SILC_CIPHER_API_SET_KEY(rc6)
-{
-  SilcUInt32 k[8];
-
-  SILC_GET_WORD_KEY(key, k, keylen);
-  rc6_set_key((RC6Context *)context, k, keylen);
-
-  return TRUE;
-}
-
-/* Sets the string as a new key for the cipher. The string is first
-   hashed and then used as a new key. */
-
-SILC_CIPHER_API_SET_KEY_WITH_STRING(rc6)
-{
-  return FALSE;
-}
-
-/* Encrypts with the cipher in CBC mode. Source and destination buffers
-   maybe one and same. */
-
-SILC_CIPHER_API_ENCRYPT_CBC(rc6)
-{
-  SilcUInt32 tiv[4];
-  int i;
-
-  SILC_CBC_GET_IV(tiv, iv);
-
-  SILC_CBC_ENC_PRE(tiv, src);
-  rc6_encrypt((RC6Context *)context, tiv, tiv);
-  SILC_CBC_ENC_POST(tiv, dst, src);
-
-  for (i = 16; i < len; i += 16) {
-    SILC_CBC_ENC_PRE(tiv, src);
-    rc6_encrypt((RC6Context *)context, tiv, tiv);
-    SILC_CBC_ENC_POST(tiv, dst, src);
-  }
-
-  SILC_CBC_PUT_IV(tiv, iv);
-
-  return TRUE;
-}
-
-/* Decrypts with the cipher in CBC mode. Source and destination buffers
-   maybe one and same. */
-
-SILC_CIPHER_API_DECRYPT_CBC(rc6)
-{
-  SilcUInt32 tmp[4], tmp2[4], tiv[4];
-  int i;
-
-  SILC_CBC_GET_IV(tiv, iv);
-
-  SILC_CBC_DEC_PRE(tmp, src);
-  rc6_decrypt((RC6Context *)context, tmp, tmp2);
-  SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
-
-  for (i = 16; i < len; i += 16) {
-    SILC_CBC_DEC_PRE(tmp, src);
-    rc6_decrypt((RC6Context *)context, tmp, tmp2);
-    SILC_CBC_DEC_POST(tmp2, dst, src, tmp, tiv);
-  }
-  
-  SILC_CBC_PUT_IV(tiv, iv);
-
-  return TRUE;
-}
-
-/* Returns the size of the cipher context. */
-
-SILC_CIPHER_API_CONTEXT_LEN(rc6)
-{
-  return sizeof(RC6Context);
-}
-
-
-#define f_rnd(i,a,b,c,d)                    \
-        u = rotl(d * (d + d + 1), 5);       \
-        t = rotl(b * (b + b + 1), 5);       \
-        a = rotl(a ^ t, u) + l_key[i];      \
-        c = rotl(c ^ u, t) + l_key[i + 1]
-
-#define i_rnd(i,a,b,c,d)                    \
-        u = rotl(d * (d + d + 1), 5);       \
-        t = rotl(b * (b + b + 1), 5);       \
-        c = rotr(c - l_key[i + 1], t) ^ u;  \
-        a = rotr(a - l_key[i], u) ^ t
-
-/* initialise the key schedule from the user supplied key   */
-
-u4byte *rc6_set_key(RC6Context *ctx, 
-                   const u4byte in_key[], const u4byte key_len)
-{   
-    u4byte  i, j, k, a, b, l[8], t;
-    u4byte *l_key = ctx->l_key;
-
-    l_key[0] = 0xb7e15163;
-
-    for(k = 1; k < 44; ++k)
-        
-        l_key[k] = l_key[k - 1] + 0x9e3779b9;
-
-    for(k = 0; k < key_len / 32; ++k)
-
-        l[k] = in_key[k];
-
-    t = (key_len / 32) - 1; /* t = (key_len / 32); */
-
-    a = b = i = j = 0;
-
-    for(k = 0; k < 132; ++k)
-    {   a = rotl(l_key[i] + a + b, 3); b += a;
-        b = rotl(l[j] + b, b);
-        l_key[i] = a; l[j] = b;
-        i = (i == 43 ? 0 : i + 1); /* i = (i + 1) % 44; */
-        j = (j == t ? 0 : j + 1);  /* j = (j + 1) % t; */
-    }
-
-    return l_key;
-};
-
-/* encrypt a block of text  */
-
-void rc6_encrypt(RC6Context *ctx,
-                const u4byte in_blk[4], u4byte out_blk[4])
-{   
-    u4byte  a,b,c,d,t,u;
-    u4byte *l_key = ctx->l_key;
-
-    a = in_blk[0]; b = in_blk[1] + l_key[0];
-    c = in_blk[2]; d = in_blk[3] + l_key[1];
-
-    f_rnd( 2,a,b,c,d); f_rnd( 4,b,c,d,a);
-    f_rnd( 6,c,d,a,b); f_rnd( 8,d,a,b,c);
-    f_rnd(10,a,b,c,d); f_rnd(12,b,c,d,a);
-    f_rnd(14,c,d,a,b); f_rnd(16,d,a,b,c);
-    f_rnd(18,a,b,c,d); f_rnd(20,b,c,d,a);
-    f_rnd(22,c,d,a,b); f_rnd(24,d,a,b,c);
-    f_rnd(26,a,b,c,d); f_rnd(28,b,c,d,a);
-    f_rnd(30,c,d,a,b); f_rnd(32,d,a,b,c);
-    f_rnd(34,a,b,c,d); f_rnd(36,b,c,d,a);
-    f_rnd(38,c,d,a,b); f_rnd(40,d,a,b,c);
-
-    out_blk[0] = a + l_key[42]; out_blk[1] = b;
-    out_blk[2] = c + l_key[43]; out_blk[3] = d;
-};
-
-/* decrypt a block of text  */
-
-void rc6_decrypt(RC6Context *ctx,
-                const u4byte in_blk[4], u4byte out_blk[4])
-{   
-    u4byte  a,b,c,d,t,u;
-    u4byte *l_key = ctx->l_key;
-
-    d = in_blk[3]; c = in_blk[2] - l_key[43]; 
-    b = in_blk[1]; a = in_blk[0] - l_key[42];
-
-    i_rnd(40,d,a,b,c); i_rnd(38,c,d,a,b);
-    i_rnd(36,b,c,d,a); i_rnd(34,a,b,c,d);
-    i_rnd(32,d,a,b,c); i_rnd(30,c,d,a,b);
-    i_rnd(28,b,c,d,a); i_rnd(26,a,b,c,d);
-    i_rnd(24,d,a,b,c); i_rnd(22,c,d,a,b);
-    i_rnd(20,b,c,d,a); i_rnd(18,a,b,c,d);
-    i_rnd(16,d,a,b,c); i_rnd(14,c,d,a,b);
-    i_rnd(12,b,c,d,a); i_rnd(10,a,b,c,d);
-    i_rnd( 8,d,a,b,c); i_rnd( 6,c,d,a,b);
-    i_rnd( 4,b,c,d,a); i_rnd( 2,a,b,c,d);
-
-    out_blk[3] = d - l_key[1]; out_blk[2] = c; 
-    out_blk[1] = b - l_key[0]; out_blk[0] = a; 
-};
diff --git a/lib/silccrypt/rc6.h b/lib/silccrypt/rc6.h
deleted file mode 100644 (file)
index c1d2ec0..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-
-  rc6.h
-
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
-
-  Copyright (C) 1997 - 2000 Pekka Riikonen
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
-
-*/
-
-#ifndef RC6_H
-#define RC6_H
-
-/* 
- * SILC Crypto API for RC6
- */
-
-SILC_CIPHER_API_SET_KEY(rc6);
-SILC_CIPHER_API_SET_KEY_WITH_STRING(rc6);
-SILC_CIPHER_API_CONTEXT_LEN(rc6);
-SILC_CIPHER_API_ENCRYPT_CBC(rc6);
-SILC_CIPHER_API_DECRYPT_CBC(rc6);
-
-#endif
diff --git a/lib/silccrypt/rc6_internal.h b/lib/silccrypt/rc6_internal.h
deleted file mode 100644 (file)
index 1b69306..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-
-  rc6_internal.h
-
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
-
-  Copyright (C) 1997 - 2000 Pekka Riikonen
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
-
-*/
-
-#ifndef RC6_INTERNAL_H
-#define RC6_INTERNAL_H
-
-#include "ciphers_def.h"
-
-/* Cipher's context */
-typedef struct {
-  u4byte l_key[44];
-} RC6Context;
-
-/* Prototypes */
-u4byte *rc6_set_key(RC6Context *ctx, 
-                   const u4byte in_key[], const u4byte key_len);
-void rc6_encrypt(RC6Context *ctx,
-                const u4byte in_blk[4], u4byte out_blk[4]);
-void rc6_decrypt(RC6Context *ctx,
-                const u4byte in_blk[4], u4byte out_blk[4]);
-
-#endif
index 7bacd1e098af114fd4663eb4c6b5f9c1720bb3fc..7f9beb17d727d02cd835bbfeb7e90474b75c908b 100644 (file)
@@ -1,10 +1,10 @@
-/* 
+/*
  * rsa.c       RSA Public and Private key generation functions,
  *             RSA encrypt and decrypt functions.
  *
- * Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ * Author: Pekka Riikonen <priikone@silcnet.org>
  *
- * Copyright (C) 1997 - 2001 Pekka Riikonen
+ * Copyright (C) 1997 - 2003 Pekka Riikonen
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *     Decryption:
  *     m = c ^ d mod n
  *
- * The SSH's (Secure Shell), PGP's (Pretty Good Privacy) and RSAREF 
- * Toolkit were used as reference when coding this implementation. They 
+ * Supports CRT (Chinese Remainder Theorem) for private key operations.
+ *
+ * The SSH's (Secure Shell), PGP's (Pretty Good Privacy) and RSAREF
+ * Toolkit were used as reference when coding this implementation. They
  * all were a big help for me.
  *
- * I also suggest reading Bruce Schneier's; Applied Cryptography, Second 
- * Edition, John Wiley & Sons, Inc. 1996. This book deals about RSA and 
+ * I also suggest reading Bruce Schneier's; Applied Cryptography, Second
+ * Edition, John Wiley & Sons, Inc. 1996. This book deals about RSA and
  * everything else too about cryptography.
  *
  */
@@ -63,7 +65,7 @@
 
    o Sat Mar 16 18:27:19 EET 2002  Pekka
 
-     Use the SilcRng sent as argument to SILC_PKCS_API_INIT in prime 
+     Use the SilcRng sent as argument to SILC_PKCS_API_INIT in prime
      generation.
 
    o Sat Sep 26 19:59:48 EEST 2002  Pekka
@@ -89,6 +91,9 @@ SILC_PKCS_API_INIT(rsa)
   SilcMPInt p, q;
   bool found = FALSE;
 
+  if (keylen < 768 || keylen > 16384)
+    return FALSE;
+
   printf("Generating RSA Public and Private keys, might take a while...\n");
 
   silc_mp_init(&p);
@@ -98,7 +103,7 @@ SILC_PKCS_API_INIT(rsa)
   while (!found) {
     printf("Finding p: ");
     silc_math_gen_prime(&p, prime_bits, TRUE, rng);
-    
+
     printf("\nFinding q: ");
     silc_math_gen_prime(&q, prime_bits, TRUE, rng);
 
@@ -125,7 +130,7 @@ SILC_PKCS_API_INIT(rsa)
 
   silc_mp_uninit(&p);
   silc_mp_uninit(&q);
-  
+
   printf("\nKeys generated successfully.\n");
 
   return TRUE;
@@ -180,45 +185,75 @@ SILC_PKCS_API_GET_PUBLIC_KEY(rsa)
 SILC_PKCS_API_GET_PRIVATE_KEY(rsa)
 {
   RsaKey *key = (RsaKey *)context;
-  unsigned char *e, *n, *d, *ret;
-  SilcUInt32 e_len, n_len, d_len;
-  unsigned char tmp[4];
+  SilcBuffer buf;
+  unsigned char *e, *n, *d, *ret, *dp = NULL, *dq = NULL;
+  unsigned char *pq = NULL, *qp = NULL, *p = NULL, *q = NULL;
+  SilcUInt32 e_len, n_len, d_len, dp_len, dq_len, pq_len, qp_len, p_len, q_len;
+  SilcUInt32 len = 0;
 
   e = silc_mp_mp2bin(&key->e, 0, &e_len);
   n = silc_mp_mp2bin(&key->n, (key->bits + 7) / 8, &n_len);
   d = silc_mp_mp2bin(&key->d, 0, &d_len);
+  if (key->crt) {
+    dp = silc_mp_mp2bin(&key->dP, 0, &dp_len);
+    dq = silc_mp_mp2bin(&key->dQ, 0, &dq_len);
+    pq = silc_mp_mp2bin(&key->pQ, 0, &pq_len);
+    qp = silc_mp_mp2bin(&key->qP, 0, &qp_len);
+    p = silc_mp_mp2bin(&key->p, 0, &p_len);
+    q = silc_mp_mp2bin(&key->q, 0, &q_len);
+    len = dp_len + 4 + dq_len + 4 + pq_len + 4 + qp_len + 4 + p_len + 4 +
+      q_len + 4;
+  }
 
-  *ret_len = e_len + 4 + n_len + 4 + d_len + 4;
-  ret = silc_calloc(*ret_len, sizeof(unsigned char));
-
-  /* Put the length of the e. */
-  SILC_PUT32_MSB(e_len, tmp);
-  memcpy(ret, tmp, 4);
-
-  /* Put the e. */
-  memcpy(ret + 4, e, e_len);
-
-  /* Put the length of the n. */
-  SILC_PUT32_MSB(n_len, tmp);
-  memcpy(ret + 4 + e_len, tmp, 4);
-
-  /* Put the n. */
-  memcpy(ret + 4 + e_len + 4, n, n_len);
-
-  /* Put the length of the d. */
-  SILC_PUT32_MSB(d_len, tmp);
-  memcpy(ret + 4 + e_len + 4 + n_len, tmp, 4);
-
-  /* Put the n. */
-  memcpy(ret + 4 + e_len + 4 + n_len + 4, d, d_len);
+  buf = silc_buffer_alloc_size(e_len + 4 + n_len + 4 + d_len + 4 + len);
+  len = silc_buffer_format(buf,
+                          SILC_STR_UI_INT(e_len),
+                          SILC_STR_UI_XNSTRING(e, e_len),
+                          SILC_STR_UI_INT(n_len),
+                          SILC_STR_UI_XNSTRING(n, n_len),
+                          SILC_STR_UI_INT(d_len),
+                          SILC_STR_UI_XNSTRING(d, d_len),
+                          SILC_STR_END);
+
+  if (key->crt) {
+    silc_buffer_pull(buf, len);
+    silc_buffer_format(buf,
+                      SILC_STR_UI_INT(dp_len),
+                      SILC_STR_UI_XNSTRING(dp, dp_len),
+                      SILC_STR_UI_INT(dq_len),
+                      SILC_STR_UI_XNSTRING(dq, dq_len),
+                      SILC_STR_UI_INT(pq_len),
+                      SILC_STR_UI_XNSTRING(pq, pq_len),
+                      SILC_STR_UI_INT(qp_len),
+                      SILC_STR_UI_XNSTRING(qp, qp_len),
+                      SILC_STR_UI_INT(p_len),
+                      SILC_STR_UI_XNSTRING(p, p_len),
+                      SILC_STR_UI_INT(q_len),
+                      SILC_STR_UI_XNSTRING(q, q_len),
+                      SILC_STR_END);
+    silc_buffer_push(buf, len);
+
+    memset(dp, 0, dp_len);
+    memset(dq, 0, dq_len);
+    memset(pq, 0, pq_len);
+    memset(qp, 0, qp_len);
+    memset(p, 0, p_len);
+    memset(q, 0, q_len);
+    silc_free(dp);
+    silc_free(dq);
+    silc_free(pq);
+    silc_free(qp);
+    silc_free(p);
+    silc_free(q);
+  }
 
-  memset(e, 0, e_len);
-  memset(n, 0, n_len);
   memset(d, 0, d_len);
   silc_free(e);
   silc_free(n);
   silc_free(d);
 
+  ret = silc_buffer_steal(buf, ret_len);
+  silc_buffer_free(buf);
   return ret;
 }
 
@@ -281,8 +316,9 @@ SILC_PKCS_API_SET_PUBLIC_KEY(rsa)
 SILC_PKCS_API_SET_PRIVATE_KEY(rsa)
 {
   RsaKey *key = (RsaKey *)context;
-  unsigned char tmp[4];
-  SilcUInt32 e_len, n_len, d_len;
+  SilcBufferStruct k;
+  unsigned char *tmp;
+  SilcUInt32 len;
 
   if (key->prv_set) {
     silc_mp_uninit(&key->d);
@@ -298,62 +334,148 @@ SILC_PKCS_API_SET_PRIVATE_KEY(rsa)
   if (key_len < 4)
     return FALSE;
 
+  silc_buffer_set(&k, key_data, key_len);
+
   silc_mp_init(&key->e);
   silc_mp_init(&key->n);
   silc_mp_init(&key->d);
+  key->prv_set = TRUE;
+  key->pub_set = TRUE;
 
-  memcpy(tmp, key_data, 4);
-  SILC_GET32_MSB(e_len, tmp);
-  if (e_len + 4 > key_len) {
-    silc_mp_uninit(&key->e);
-    silc_mp_uninit(&key->n);
-    silc_mp_uninit(&key->d);
-    return FALSE;
-  }
-
-  silc_mp_bin2mp(key_data + 4, e_len, &key->e);
-  
-  if (key_len < e_len + 4 + 4) {
-    silc_mp_uninit(&key->e);
-    silc_mp_uninit(&key->n);
-    silc_mp_uninit(&key->d);
-    return FALSE;
-  }
-
-  memcpy(tmp, key_data + 4 + e_len, 4);
-  SILC_GET32_MSB(n_len, tmp);
-  if (e_len + 4 + n_len + 4 > key_len) {
-    silc_mp_uninit(&key->e);
-    silc_mp_uninit(&key->n);
-    silc_mp_uninit(&key->d);
-    return FALSE;
-  }
-
-  silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &key->n);
-
-  if (key_len < e_len + 4 + n_len + 4 + 4) {
-    silc_mp_uninit(&key->e);
-    silc_mp_uninit(&key->n);
-    silc_mp_uninit(&key->d);
-    return FALSE;
-  }
-
-  memcpy(tmp, key_data + 4 + e_len + 4 + n_len, 4);
-  SILC_GET32_MSB(d_len, tmp);
-  if (e_len + 4 + n_len + 4 + d_len + 4 > key_len) {
-    silc_mp_uninit(&key->e);
-    silc_mp_uninit(&key->n);
-    silc_mp_uninit(&key->d);
-    return FALSE;
+  /* Get e */
+  if (silc_buffer_unformat(&k,
+                          SILC_STR_UI_INT(&len),
+                          SILC_STR_END) < 0)
+    goto err;
+  silc_buffer_pull(&k, 4);
+  if (silc_buffer_unformat(&k,
+                          SILC_STR_UI_XNSTRING(&tmp, len),
+                          SILC_STR_END) < 0)
+    goto err;
+  silc_mp_bin2mp(tmp, len, &key->e);
+  silc_buffer_pull(&k, len);
+
+  /* Get n */
+  if (silc_buffer_unformat(&k,
+                          SILC_STR_UI_INT(&len),
+                          SILC_STR_END) < 0)
+    goto err;
+  silc_buffer_pull(&k, 4);
+  if (silc_buffer_unformat(&k,
+                          SILC_STR_UI_XNSTRING(&tmp, len),
+                          SILC_STR_END) < 0)
+    goto err;
+  silc_mp_bin2mp(tmp, len, &key->n);
+  silc_buffer_pull(&k, len);
+
+  /* Get d */
+  if (silc_buffer_unformat(&k,
+                          SILC_STR_UI_INT(&len),
+                          SILC_STR_END) < 0)
+    goto err;
+  silc_buffer_pull(&k, 4);
+  if (silc_buffer_unformat(&k,
+                          SILC_STR_UI_XNSTRING(&tmp, len),
+                          SILC_STR_END) < 0)
+    goto err;
+  silc_mp_bin2mp(tmp, len, &key->d);
+  silc_buffer_pull(&k, len);
+
+  /* Get optimized d for CRT, if present. */
+  if (k.len > 4) {
+    key->crt = TRUE;
+    silc_mp_init(&key->dP);
+    silc_mp_init(&key->dQ);
+    silc_mp_init(&key->pQ);
+    silc_mp_init(&key->qP);
+    silc_mp_init(&key->p);
+    silc_mp_init(&key->q);
+
+    /* Get dP */
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_INT(&len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_buffer_pull(&k, 4);
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_XNSTRING(&tmp, len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_mp_bin2mp(tmp, len, &key->dP);
+    silc_buffer_pull(&k, len);
+
+    /* Get dQ */
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_INT(&len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_buffer_pull(&k, 4);
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_XNSTRING(&tmp, len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_mp_bin2mp(tmp, len, &key->dQ);
+    silc_buffer_pull(&k, len);
+
+    /* Get pQ */
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_INT(&len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_buffer_pull(&k, 4);
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_XNSTRING(&tmp, len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_mp_bin2mp(tmp, len, &key->pQ);
+    silc_buffer_pull(&k, len);
+
+    /* Get qP */
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_INT(&len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_buffer_pull(&k, 4);
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_XNSTRING(&tmp, len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_mp_bin2mp(tmp, len, &key->qP);
+    silc_buffer_pull(&k, len);
+
+    /* Get p */
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_INT(&len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_buffer_pull(&k, 4);
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_XNSTRING(&tmp, len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_mp_bin2mp(tmp, len, &key->p);
+    silc_buffer_pull(&k, len);
+
+    /* Get q */
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_INT(&len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_buffer_pull(&k, 4);
+    if (silc_buffer_unformat(&k,
+                            SILC_STR_UI_XNSTRING(&tmp, len),
+                            SILC_STR_END) < 0)
+      goto err;
+    silc_mp_bin2mp(tmp, len, &key->q);
+    silc_buffer_pull(&k, len);
   }
 
-  silc_mp_bin2mp(key_data + 4 + e_len + 4 + n_len + 4, d_len, &key->d);
-
   key->bits = silc_mp_sizeinbase(&key->n, 2);
-  key->prv_set = TRUE;
-  key->pub_set = TRUE;
-
   return key->bits;
+
+ err:
+  rsa_clear_keys(key);
+  return FALSE;
 }
 
 SILC_PKCS_API_CONTEXT_LEN(rsa)
@@ -361,6 +483,8 @@ SILC_PKCS_API_CONTEXT_LEN(rsa)
   return sizeof(RsaKey);
 }
 
+/* Raw RSA routines */
+
 SILC_PKCS_API_ENCRYPT(rsa)
 {
   RsaKey *key = (RsaKey *)context;
@@ -375,8 +499,8 @@ SILC_PKCS_API_ENCRYPT(rsa)
   silc_mp_bin2mp(src, src_len, &mp_tmp);
 
   /* Encrypt */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
-  
+  rsa_public_operation(key, &mp_tmp, &mp_dst);
+
   tmplen = (key->bits + 7) / 8;
 
   /* Format the MP int back into data */
@@ -403,7 +527,7 @@ SILC_PKCS_API_DECRYPT(rsa)
   silc_mp_bin2mp(src, src_len, &mp_tmp);
 
   /* Decrypt */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
+  rsa_private_operation(key, &mp_tmp, &mp_dst);
 
   tmplen = (key->bits + 7) / 8;
 
@@ -431,7 +555,7 @@ SILC_PKCS_API_SIGN(rsa)
   silc_mp_bin2mp(src, src_len, &mp_tmp);
 
   /* Sign */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
+  rsa_private_operation(key, &mp_tmp, &mp_dst);
 
   tmplen = (key->bits + 7) / 8;
 
@@ -460,7 +584,7 @@ SILC_PKCS_API_VERIFY(rsa)
   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
 
   /* Verify */
-  rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
+  rsa_public_operation(key, &mp_tmp2, &mp_dst);
 
   /* Format the data into MP int */
   silc_mp_bin2mp(data, data_len, &mp_tmp);
@@ -478,21 +602,186 @@ SILC_PKCS_API_VERIFY(rsa)
   return ret;
 }
 
+
+/* PKCS#1 RSA routines */
+
+SILC_PKCS_API_ENCRYPT(pkcs1)
+{
+  RsaKey *key = (RsaKey *)context;
+  SilcMPInt mp_tmp;
+  SilcMPInt mp_dst;
+  unsigned char padded[2048 + 1];
+  SilcUInt32 len = (key->bits + 7) / 8;
+
+  if (sizeof(padded) < len)
+    return FALSE;
+
+  /* Pad data */
+  if (!silc_pkcs1_encode(SILC_PKCS1_BT_PUB, src, src_len,
+                        padded, len, NULL))
+    return FALSE;
+
+  silc_mp_init(&mp_tmp);
+  silc_mp_init(&mp_dst);
+
+  /* Data to MP */
+  silc_mp_bin2mp(padded, len, &mp_tmp);
+
+  /* Encrypt */
+  rsa_public_operation(key, &mp_tmp, &mp_dst);
+
+  /* MP to data */
+  silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
+  *dst_len = len;
+
+  memset(padded, 0, sizeof(padded));
+  silc_mp_uninit(&mp_tmp);
+  silc_mp_uninit(&mp_dst);
+
+  return TRUE;
+}
+
+SILC_PKCS_API_DECRYPT(pkcs1)
+{
+  RsaKey *key = (RsaKey *)context;
+  SilcMPInt mp_tmp;
+  SilcMPInt mp_dst;
+  unsigned char *padded, unpadded[2048 + 1];
+  SilcUInt32 padded_len;
+
+  silc_mp_init(&mp_tmp);
+  silc_mp_init(&mp_dst);
+
+  /* Data to MP */
+  silc_mp_bin2mp(src, src_len, &mp_tmp);
+
+  /* Decrypt */
+  rsa_private_operation(key, &mp_tmp, &mp_dst);
+
+  /* MP to data */
+  padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
+
+  /* Unpad data */
+  if (!silc_pkcs1_decode(SILC_PKCS1_BT_PUB, padded, padded_len,
+                        unpadded, sizeof(unpadded), dst_len)) {
+    memset(padded, 0, padded_len);
+    silc_free(padded);
+    silc_mp_uninit(&mp_tmp);
+    silc_mp_uninit(&mp_dst);
+    return FALSE;
+  }
+
+  /* Copy to destination */
+  memcpy(dst, unpadded, *dst_len);
+
+  memset(padded, 0, padded_len);
+  memset(unpadded, 0, sizeof(unpadded));
+  silc_free(padded);
+  silc_mp_uninit(&mp_tmp);
+  silc_mp_uninit(&mp_dst);
+
+  return TRUE;
+}
+
+SILC_PKCS_API_SIGN(pkcs1)
+{
+  RsaKey *key = (RsaKey *)context;
+  SilcMPInt mp_tmp;
+  SilcMPInt mp_dst;
+  unsigned char padded[2048 + 1];
+  SilcUInt32 len = (key->bits + 7) / 8;
+
+  if (sizeof(padded) < len)
+    return FALSE;
+
+  /* Pad data */
+  if (!silc_pkcs1_encode(SILC_PKCS1_BT_PRV1, src, src_len,
+                        padded, len, NULL))
+    return FALSE;
+
+  silc_mp_init(&mp_tmp);
+  silc_mp_init(&mp_dst);
+
+  /* Data to MP */
+  silc_mp_bin2mp(padded, len, &mp_tmp);
+
+  /* Sign */
+  rsa_private_operation(key, &mp_tmp, &mp_dst);
+
+  /* MP to data */
+  silc_mp_mp2bin_noalloc(&mp_dst, dst, len);
+  *dst_len = len;
+
+  memset(padded, 0, sizeof(padded));
+  silc_mp_uninit(&mp_tmp);
+  silc_mp_uninit(&mp_dst);
+
+  return TRUE;
+}
+
+SILC_PKCS_API_VERIFY(pkcs1)
+{
+  RsaKey *key = (RsaKey *)context;
+  int ret = TRUE;
+  SilcMPInt mp_tmp2;
+  SilcMPInt mp_dst;
+  unsigned char *verify, unpadded[2048 + 1];
+  SilcUInt32 verify_len, len = (key->bits + 7) / 8;
+
+  silc_mp_init(&mp_tmp2);
+  silc_mp_init(&mp_dst);
+
+  /* Format the signature into MP int */
+  silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
+
+  /* Verify */
+  rsa_public_operation(key, &mp_tmp2, &mp_dst);
+
+  /* MP to data */
+  verify = silc_mp_mp2bin(&mp_dst, len, &verify_len);
+
+  /* Unpad data */
+  if (!silc_pkcs1_decode(SILC_PKCS1_BT_PRV1, verify, verify_len,
+                        unpadded, sizeof(unpadded), &len)) {
+    memset(verify, 0, verify_len);
+    silc_free(verify);
+    silc_mp_uninit(&mp_tmp2);
+    silc_mp_uninit(&mp_dst);
+    return FALSE;
+  }
+
+  /* Compare */
+  if (memcmp(data, unpadded, len))
+    ret = FALSE;
+
+  memset(verify, 0, verify_len);
+  memset(unpadded, 0, sizeof(unpadded));
+  silc_free(verify);
+  silc_mp_uninit(&mp_tmp2);
+  silc_mp_uninit(&mp_dst);
+
+  return ret;
+}
+
 /* Generates RSA public and private keys. Primes p and q that are used
    to compute the modulus n has to be generated before calling this. They
    are then sent as argument for the function. */
 
-void rsa_generate_keys(RsaKey *key, SilcUInt32 bits, 
+bool rsa_generate_keys(RsaKey *key, SilcUInt32 bits,
                       SilcMPInt *p, SilcMPInt *q)
 {
   SilcMPInt phi, hlp;
   SilcMPInt div, lcm;
   SilcMPInt pm1, qm1;
-  
+
   /* Initialize variables */
   silc_mp_init(&key->n);
   silc_mp_init(&key->e);
   silc_mp_init(&key->d);
+  silc_mp_init(&key->dP);
+  silc_mp_init(&key->dQ);
+  silc_mp_init(&key->pQ);
+  silc_mp_init(&key->qP);
   silc_mp_init(&phi);
   silc_mp_init(&hlp);
   silc_mp_init(&div);
@@ -505,41 +794,56 @@ void rsa_generate_keys(RsaKey *key, SilcUInt32 bits,
 
   /* Compute modulus, n = p * q */
   silc_mp_mul(&key->n, p, q);
-  
+
   /* phi = (p - 1) * (q - 1) */
   silc_mp_sub_ui(&pm1, p, 1);
   silc_mp_sub_ui(&qm1, q, 1);
   silc_mp_mul(&phi, &pm1, &qm1);
-  
+
   /* Set e, the public exponent. We try to use same public exponent
-     for all keys. Also, to make encryption faster we use small 
+     for all keys. Also, to make encryption faster we use small
      number. */
   silc_mp_set_ui(&key->e, 65533);
  retry_e:
   /* See if e is relatively prime to phi. gcd == greates common divisor,
      if gcd equals 1 they are relatively prime. */
   silc_mp_gcd(&hlp, &key->e, &phi);
-  if((silc_mp_cmp_ui(&hlp, 1)) > 0) {
+  if ((silc_mp_cmp_ui(&hlp, 1)) > 0) {
     silc_mp_add_ui(&key->e, &key->e, 2);
     goto retry_e;
   }
-  
+
   /* Find d, the private exponent, e ^ -1 mod lcm(phi). */
   silc_mp_gcd(&div, &pm1, &qm1);
   silc_mp_div(&lcm, &phi, &div);
   silc_mp_modinv(&key->d, &key->e, &lcm);
-  
+
+  /* Optimize d with CRT.  We precompute as much as possible. */
+  silc_mp_mod(&key->dP, &key->d, &pm1);
+  silc_mp_mod(&key->dQ, &key->d, &qm1);
+  silc_mp_modinv(&key->pQ, p, q);
+  silc_mp_mul(&key->pQ, p, &key->pQ);
+  silc_mp_mod(&key->pQ, &key->pQ, &key->n);
+  silc_mp_modinv(&key->qP, q, p);
+  silc_mp_mul(&key->qP, q, &key->qP);
+  silc_mp_mod(&key->qP, &key->qP, &key->n);
+  silc_mp_set(&key->p, p);
+  silc_mp_set(&key->q, q);
+  key->crt = TRUE;
+
   silc_mp_uninit(&phi);
   silc_mp_uninit(&hlp);
   silc_mp_uninit(&div);
   silc_mp_uninit(&lcm);
   silc_mp_uninit(&pm1);
   silc_mp_uninit(&qm1);
+
+  return TRUE;
 }
 
 /* Clears whole key structure. */
 
-void rsa_clear_keys(RsaKey *key)
+bool rsa_clear_keys(RsaKey *key)
 {
   key->bits = 0;
   if (key->pub_set) {
@@ -548,18 +852,49 @@ void rsa_clear_keys(RsaKey *key)
   }
   if (key->prv_set)
     silc_mp_uninit(&key->d);
+  if (key->prv_set && key->crt) {
+    silc_mp_uninit(&key->dP);
+    silc_mp_uninit(&key->dQ);
+    silc_mp_uninit(&key->pQ);
+    silc_mp_uninit(&key->qP);
+    silc_mp_uninit(&key->p);
+    silc_mp_uninit(&key->q);
+  }
+  return TRUE;
 }
 
-/* RSA encrypt/decrypt function. cm = ciphertext or plaintext,
-   mc = plaintext or ciphertext, expo = public or private exponent,
-   and modu = modulus. 
+/* RSA public key operation */
 
-   Encrypt: c = m ^ e mod n,
-   Decrypt: m = c ^ d mod n 
-*/
+bool rsa_public_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst)
+{
+  /* dst = src ^ e mod n */
+  silc_mp_pow_mod(dst, src, &key->e, &key->n);
+  return TRUE;
+}
+
+/* RSA private key operation */
 
-void rsa_en_de_crypt(SilcMPInt *cm, SilcMPInt *mc, 
-                    SilcMPInt *expo, SilcMPInt *modu)
+bool rsa_private_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst)
 {
-  silc_mp_pow_mod(cm, mc, expo, modu);
+  if (!key->crt) {
+    /* dst = src ^ d mod n */
+    silc_mp_pow_mod(dst, src, &key->d, &key->n);
+  } else {
+    /* CRT */
+    SilcMPInt tmp;
+
+    silc_mp_init(&tmp);
+
+    /* dst = ((src ^ dP mod p) * qP) + ((src ^ dQ mod q) * pQ) mod n */
+    silc_mp_pow_mod(dst, src, &key->dP, &key->p);
+    silc_mp_mul(dst, dst, &key->qP);
+    silc_mp_pow_mod(&tmp, src, &key->dQ, &key->q);
+    silc_mp_mul(&tmp, &tmp, &key->pQ);
+    silc_mp_add(dst, dst, &tmp);
+    silc_mp_mod(dst, dst, &key->n);
+
+    silc_mp_uninit(&tmp);
+  }
+
+  return TRUE;
 }
index 5f8262fa80f85c7194c6c8bec9b2c1b3c9e060b9..a697fef493a8c6d51bddfc33d221e5964a6c9d11 100644 (file)
@@ -2,15 +2,14 @@
 
   rsa.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -37,5 +36,10 @@ SILC_PKCS_API_DECRYPT(rsa);
 SILC_PKCS_API_SIGN(rsa);
 SILC_PKCS_API_VERIFY(rsa);
 
+SILC_PKCS_API_ENCRYPT(pkcs1);
+SILC_PKCS_API_DECRYPT(pkcs1);
+SILC_PKCS_API_SIGN(pkcs1);
+SILC_PKCS_API_VERIFY(pkcs1);
+
 
 #endif
index 22904bbfd1e70efa475cd59eae187c0efc0c980c..425ce6a96e57b0359d4b75994248e23e0b560fbc 100644 (file)
@@ -2,15 +2,15 @@
 
   rsa_internal.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, 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
 /* RSA Keys, includes both Private and Public key */
 typedef struct {
   int bits;                    /* bits in key */
-  char pub_set;                        /* TRUE is n and e is set */
-  char prv_set;                        /* TRUE if d is set */
   SilcMPInt n;                 /* modulus */
   SilcMPInt e;                 /* public exponent */
-  SilcMPInt d;                 /* private exponent */
+  SilcMPInt d;                 /* private exponent (no CRT) */
+  SilcMPInt p;                 /* p */
+  SilcMPInt q;                 /* q */
+  SilcMPInt dP;                        /* CRT, d mod p - 1 */
+  SilcMPInt dQ;                        /* CRT, d mod q - 1 */
+  SilcMPInt pQ;                        /* CRT, p * (p ^ -1 mod q) mod n */
+  SilcMPInt qP;                        /* CRT, q * (q ^ -1 mod p) mod n */
+  unsigned int pub_set : 1;    /* TRUE if n and e is set */
+  unsigned int prv_set : 1;    /* TRUE if d is set */
+  unsigned int crt     : 1;    /* TRUE if CRT is used */
 } RsaKey;
 
-void rsa_generate_keys(RsaKey *key, SilcUInt32 bits, 
+bool rsa_generate_keys(RsaKey *key, SilcUInt32 bits,
                       SilcMPInt *p, SilcMPInt *q);
-void rsa_clear_keys(RsaKey *key);
-void rsa_en_de_crypt(SilcMPInt *cm, SilcMPInt *mc, 
-                    SilcMPInt *expo, SilcMPInt *modu);
+bool rsa_clear_keys(RsaKey *key);
+bool rsa_public_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst);
+bool rsa_private_operation(RsaKey *key, SilcMPInt *src, SilcMPInt *dst);
 
 #endif
index 53c938b69a17e475d44ba9f7392bf993911a99ea..378bd73cc1d93d677dd0ec4e737c00903ff4d685 100644 (file)
@@ -2,15 +2,14 @@
 
   silccipher.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -37,47 +36,38 @@ SilcDList silc_cipher_list = NULL;
 /* Static list of ciphers for silc_cipher_register_default(). */
 const SilcCipherObject silc_default_ciphers[] =
 {
-  { "aes-256-cbc", 16, 256, silc_aes_set_key, 
+  { "aes-256-cbc", 16, 256, silc_aes_set_key,
     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
     silc_aes_decrypt_cbc, silc_aes_context_len },
-  { "aes-192-cbc", 16, 192, silc_aes_set_key, 
+  { "aes-192-cbc", 16, 192, silc_aes_set_key,
     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
     silc_aes_decrypt_cbc, silc_aes_context_len },
-  { "aes-128-cbc", 16, 128, silc_aes_set_key, 
+  { "aes-128-cbc", 16, 128, silc_aes_set_key,
     silc_aes_set_key_with_string, silc_aes_encrypt_cbc,
     silc_aes_decrypt_cbc, silc_aes_context_len },
-  { "twofish-256-cbc", 16, 256, silc_twofish_set_key, 
+  { "twofish-256-cbc", 16, 256, silc_twofish_set_key,
     silc_twofish_set_key_with_string,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
+    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
     silc_twofish_context_len },
-  { "twofish-192-cbc", 16, 192, silc_twofish_set_key, 
+  { "twofish-192-cbc", 16, 192, silc_twofish_set_key,
     silc_twofish_set_key_with_string,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
+    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
     silc_twofish_context_len },
-  { "twofish-128-cbc", 16, 128, silc_twofish_set_key, 
+  { "twofish-128-cbc", 16, 128, silc_twofish_set_key,
     silc_twofish_set_key_with_string,
-    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc, 
+    silc_twofish_encrypt_cbc, silc_twofish_decrypt_cbc,
     silc_twofish_context_len },
-  { "rc6-256-cbc", 16, 256, silc_rc6_set_key, silc_rc6_set_key_with_string,
-    silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
-    silc_rc6_context_len },
-  { "rc6-192-cbc", 16, 192, silc_rc6_set_key, silc_rc6_set_key_with_string,
-    silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
-    silc_rc6_context_len },
-  { "rc6-128-cbc", 16, 128, silc_rc6_set_key, silc_rc6_set_key_with_string,
-    silc_rc6_encrypt_cbc, silc_rc6_decrypt_cbc, 
-    silc_rc6_context_len },
   { "cast-256-cbc", 16, 256, silc_cast_set_key, silc_cast_set_key_with_string,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
+    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
     silc_cast_context_len },
   { "cast-192-cbc", 16, 192, silc_cast_set_key, silc_cast_set_key_with_string,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
+    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
     silc_cast_context_len },
   { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
-    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc, 
+    silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
     silc_cast_context_len },
   { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
-    silc_none_encrypt_cbc, silc_none_decrypt_cbc, 
+    silc_none_encrypt_cbc, silc_none_decrypt_cbc,
     silc_none_context_len },
 
   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
@@ -156,7 +146,7 @@ bool silc_cipher_unregister(SilcCipherObject *cipher)
   return FALSE;
 }
 
-/* Function that registers all the default ciphers (all builtin ciphers). 
+/* Function that registers all the default ciphers (all builtin ciphers).
    The application may use this to register the default ciphers if specific
    ciphers in any specific order is not wanted. */
 
@@ -190,7 +180,7 @@ bool silc_cipher_unregister_all(void)
   return TRUE;
 }
 
-/* Allocates a new SILC cipher object. Function returns 1 on succes and 0 
+/* Allocates a new SILC cipher object. Function returns 1 on succes and 0
    on error. The allocated cipher is returned in new_cipher argument. The
    caller must set the key to the cipher after this function has returned
    by calling the ciphers set_key function. */
@@ -200,7 +190,7 @@ bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
   SilcCipherObject *entry = NULL;
 
   SILC_LOG_DEBUG(("Allocating new cipher object"));
-  
+
 #ifndef SILC_EPOC
   if (silc_cipher_list) {
     silc_dlist_start(silc_cipher_list);
@@ -224,7 +214,7 @@ bool silc_cipher_alloc(const unsigned char *name, SilcCipher *new_cipher)
 
   if (entry) {
     *new_cipher = silc_calloc(1, sizeof(**new_cipher));
-    (*new_cipher)->cipher = entry; 
+    (*new_cipher)->cipher = entry;
     (*new_cipher)->context = silc_calloc(1, entry->context_len());
     return TRUE;
   }
@@ -281,8 +271,8 @@ char *silc_cipher_get_supported(void)
     while ((entry = silc_dlist_get(silc_cipher_list)) != SILC_LIST_END) {
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -295,8 +285,8 @@ char *silc_cipher_get_supported(void)
       entry = (SilcCipherObject *)&(silc_default_ciphers[i]);
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -312,7 +302,7 @@ char *silc_cipher_get_supported(void)
 /* Encrypts */
 
 bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
-                        unsigned char *dst, SilcUInt32 len, 
+                        unsigned char *dst, SilcUInt32 len,
                         unsigned char *iv)
 {
 #ifdef SILC_DEBUG
@@ -327,11 +317,11 @@ bool silc_cipher_encrypt(SilcCipher cipher, const unsigned char *src,
 /* Decrypts */
 
 bool silc_cipher_decrypt(SilcCipher cipher, const unsigned char *src,
-                        unsigned char *dst, SilcUInt32 len, 
+                        unsigned char *dst, SilcUInt32 len,
                         unsigned char *iv)
 {
 #ifdef SILC_DEBUG
-  assert((len & (cipher->cipher->block_len - 1)) == 0);
+  /*  assert((len & (cipher->cipher->block_len - 1)) == 0); */
 #endif
   if (len & (cipher->cipher->block_len - 1))
     return FALSE;
index 11dda7c95ad2e1d8c3f22d0101613f72b967dae4..6ce2f9fa389670e4c9991ee72267c4f418e8749a 100644 (file)
@@ -21,7 +21,6 @@
 #include "silcincludes.h"
 
 #include "rsa.h"
-#include "pkcs1.h"
 
 /* The main SILC PKCS structure. */
 struct SilcPKCSStruct {
@@ -293,7 +292,10 @@ char *silc_pkcs_get_supported(void)
 bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
                            SilcRng rng)
 {
-  return pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
+  bool ret = pkcs->pkcs->init(pkcs->context, bits_key_len, rng);
+  if (ret)
+    pkcs->key_len = bits_key_len;
+  return ret;
 }
 
 /* Returns the length of the key */
@@ -636,9 +638,8 @@ SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
   public_key = silc_calloc(1, sizeof(*public_key));
   public_key->name = strdup(name);
   public_key->pk_len = pk_len;
-  public_key->pk = silc_calloc(pk_len, sizeof(*public_key->pk));
+  public_key->pk = silc_memdup(pk, pk_len);
   public_key->pk_type = SILC_SKE_PK_TYPE_SILC;
-  memcpy(public_key->pk, pk, pk_len);
 
   if (!silc_utf8_valid(identifier, strlen(identifier))) {
     int len = silc_utf8_encoded_len(identifier, strlen(identifier), 0);
@@ -678,8 +679,7 @@ SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
   private_key = silc_calloc(1, sizeof(*private_key));
   private_key->name = strdup(name);
   private_key->prv_len = prv_len;
-  private_key->prv = silc_calloc(prv_len, sizeof(*private_key->prv));
-  memcpy(private_key->prv, prv, prv_len);
+  private_key->prv = silc_memdup(prv, prv_len);
 
   return private_key;
 }
@@ -690,7 +690,10 @@ void silc_pkcs_private_key_free(SilcPrivateKey private_key)
 {
   if (private_key) {
     silc_free(private_key->name);
-    silc_free(private_key->prv);
+    if (private_key->prv) {
+      memset(private_key->prv, 0, private_key->prv_len);
+      silc_free(private_key->prv);
+    }
     silc_free(private_key);
   }
 }
@@ -701,26 +704,10 @@ void silc_pkcs_private_key_free(SilcPrivateKey private_key)
 unsigned char *
 silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
 {
-  SilcBuffer buf;
-  unsigned char *ret;
-
-  buf = silc_buffer_alloc_size(public_key->len + 4);
-  if (!buf)
-    return NULL;
-
-  silc_buffer_format(buf,
-                    SILC_STR_UI_INT(public_key->len),
-                    SILC_STR_UI_SHORT(strlen(public_key->name)),
-                    SILC_STR_UI32_STRING(public_key->name),
-                    SILC_STR_UI_SHORT(strlen(public_key->identifier)),
-                    SILC_STR_UI32_STRING(public_key->identifier),
-                    SILC_STR_UI_XNSTRING(public_key->pk,
-                                         public_key->pk_len),
-                    SILC_STR_END);
-
-  ret = silc_buffer_steal(buf, len);
-  silc_buffer_free(buf);
-  return ret;
+  return silc_pkcs_public_key_data_encode(public_key->pk,
+                                         public_key->pk_len,
+                                         public_key->name,
+                                         public_key->identifier, len);
 }
 
 /* Encodes SILC style public key. Returns the encoded data. */
@@ -966,25 +953,9 @@ SilcPublicKey silc_pkcs_public_key_copy(SilcPublicKey public_key)
 unsigned char *
 silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
 {
-  SilcBuffer buf;
-  unsigned char *ret;
-  SilcUInt32 totlen;
-
-  totlen = 2 + strlen(private_key->name) + private_key->prv_len;
-  buf = silc_buffer_alloc_size(totlen);
-  if (!buf)
-    return NULL;
-
-  silc_buffer_format(buf,
-                    SILC_STR_UI_SHORT(strlen(private_key->name)),
-                    SILC_STR_UI32_STRING(private_key->name),
-                    SILC_STR_UI_XNSTRING(private_key->prv,
-                                         private_key->prv_len),
-                    SILC_STR_END);
-
-  ret = silc_buffer_steal(buf, len);
-  silc_buffer_free(buf);
-  return ret;
+  return silc_pkcs_private_key_data_encode(private_key->prv,
+                                          private_key->prv_len,
+                                          private_key->name, len);
 }
 
 /* Encodes SILC private key. Returns the encoded data. */
index f954542499ebb7261d077db5081cc2ccad0577f1..32463d11bbb2632d179aedd8f03d04c3057f2619 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcpkcs.h 
+  silcpkcs.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -362,6 +362,7 @@ char *silc_pkcs_get_supported(void);
  * DESCRIPTION
  *
  *    Generate new key pair into the `pkcs' context. Returns FALSE on error.
+ *    If the `rng' is NULL global SILC RNG will be used.
  *
  ***/
 bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
@@ -375,7 +376,7 @@ bool silc_pkcs_generate_key(SilcPKCS pkcs, SilcUInt32 bits_key_len,
  *
  * DESCRIPTION
  *
- *    Returns the length of the key.
+ *    Returns the length of the key in bits.
  *
  ***/
 SilcUInt32 silc_pkcs_get_key_len(SilcPKCS self);
@@ -401,8 +402,9 @@ const char *silc_pkcs_get_name(SilcPKCS pkcs);
  *
  * DESCRIPTION
  *
- *    Returns SILC style public key.  The caller must free the returned
- *    data.
+ *    Returns SILC style public key for the PKCS.  Note that this is not
+ *    the SILC Public Key, but the raw public key data from the PKCS.
+ *    The caller must free the returned data.
  *
  ***/
 unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len);
@@ -416,8 +418,9 @@ unsigned char *silc_pkcs_get_public_key(SilcPKCS pkcs, SilcUInt32 *len);
  *
  * DESCRIPTION
  *
- *    Returns SILC style private key.  The caller must free the returned
- *    data and SHOULD zero the memory area before freeing.
+ *    Returns SILC style private key.  Note that this is not SilcPrivateKey
+ *    but the raw private key bits from the PKCS.  The caller must free the
+ *    returned data and SHOULD zero the memory area before freeing.
  *
  ***/
 unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len);
@@ -431,7 +434,8 @@ unsigned char *silc_pkcs_get_private_key(SilcPKCS pkcs, SilcUInt32 *len);
  *
  * DESCRIPTION
  *
- *    Sets public key from SilcPublicKey. Returns the length of the key.
+ *    Sets public key from SilcPublicKey. Returns the length of the key in
+ *    bits.
  *
  ***/
 SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key);
@@ -461,10 +465,12 @@ SilcUInt32 silc_pkcs_public_key_data_set(SilcPKCS pkcs, unsigned char *pk,
  *
  * DESCRIPTION
  *
- *    Sets private key from SilcPrivateKey. Returns the length of the key.
+ *    Sets private key from SilcPrivateKey. Returns the length of the key
+ *    in bits.
  *
  ***/
-SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key);
+SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs,
+                                    SilcPrivateKey private_key);
 
 /****f* silccrypt/SilcPKCSAPI/silc_pkcs_private_key_data_set
  *
@@ -540,7 +546,8 @@ bool silc_pkcs_sign(SilcPKCS pkcs, unsigned char *src, SilcUInt32 src_len,
  *
  * DESCRIPTION
  *
- *    Verifies signature.  Returns FALSE on error.
+ *    Verifies signature.  Returns FALSE on error.  The 'signature' is
+ *    verified against the 'data'.
  *
  ***/
 bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
@@ -644,8 +651,11 @@ void silc_pkcs_free_identifier(SilcPublicKeyIdentifier identifier);
  *
  * DESCRIPTION
  *
- *    Allocates SILC style public key formed from sent arguments.  All data
- *    is duplicated.
+ *    Allocates SILC style public key formed from sent arguments.  The
+ *    'name' is the algorithm (PKCS) name, the 'identifier' is the public
+ *    key identifier generated with silc_pkcs_encode_identifier, and the
+ *    'pk' and 'pk_len' are the raw public key data returned for example
+ *    by silc_pkcs_get_public_key.
  *
  ***/
 SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
@@ -661,7 +671,7 @@ SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
  *
  * DESCRIPTION
  *
- *    Frees public key.
+ *    Frees public key and all data in it.
  *
  ***/
 void silc_pkcs_public_key_free(SilcPublicKey public_key);
@@ -676,8 +686,9 @@ void silc_pkcs_public_key_free(SilcPublicKey public_key);
  *
  * DESCRIPTION
  *
- *    Allocates SILC private key formed from sent arguments.  All data is
- *    duplicated.
+ *    Allocates SILC private key formed from sent arguments.  The 'name'
+ *    is the algorithm name, and the 'prv' and 'prv_len' are the raw
+ *    private key bits returned by silc_pkcs_get_private_key.
  *
  ***/
 SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
@@ -692,7 +703,8 @@ SilcPrivateKey silc_pkcs_private_key_alloc(const char *name,
  *
  * DESCRIPTION
  *
- *    Frees private key.
+ *    Frees private key and all data in it.  The private key is zeroed
+ *    before it is freed.
  *
  ***/
 void silc_pkcs_private_key_free(SilcPrivateKey private_key);
diff --git a/lib/silccrypt/silcpkcs1.c b/lib/silccrypt/silcpkcs1.c
new file mode 100644 (file)
index 0000000..c6263fb
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+
+  silcpkcs1.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2003 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+/* $Id$ */
+
+#include "silcincludes.h"
+#include "silcpkcs1.h"
+
+/* Minimum padding in block */
+#define SILC_PKCS1_MIN_PADDING 8
+
+/* Encodes PKCS#1 data block from the `data' according to the block type
+   indicated by `bt'.  When encoding signatures the `bt' must be
+   SILC_PKCS1_BT_PRV1 and when encoding encryption blocks the `bt' must
+   be SILC_PKCS1_BT_PUB.  The encoded data is copied into the `dest_data'
+   buffer which is size of `dest_data_size'.  If the `dest_data' is not
+   able to hold the encoded block this returns FALSE.  The `rng' must be
+   set when `bt' is SILC_PKCS1_BT_PUB.  This function returns TRUE on
+   success. */
+
+bool silc_pkcs1_encode(SilcPkcs1BlockType bt,
+                      const unsigned char *data,
+                      SilcUInt32 data_len,
+                      unsigned char *dest_data,
+                      SilcUInt32 dest_data_size,
+                      SilcRng rng)
+{
+  SilcInt32 padlen;
+  int i;
+
+  SILC_LOG_DEBUG(("PKCS#1 encoding, bt %d", bt));
+
+  if (!data || !dest_data ||
+      dest_data_size < 3 || dest_data_size < data_len) {
+    SILC_LOG_DEBUG(("Data to be encoded is too long"));
+    return FALSE;
+  }
+
+  /* Start of block */
+  dest_data[0] = 0x00;
+  dest_data[1] = (unsigned char)bt;
+
+  padlen = (SilcInt32)dest_data_size - (SilcInt32)data_len - 3;
+  if (padlen < SILC_PKCS1_MIN_PADDING) {
+    SILC_LOG_DEBUG(("Data to be encoded is too long"));
+    return FALSE;
+  }
+
+  /* Encode according to block type */
+  switch (bt) {
+  case SILC_PKCS1_BT_PRV0:
+  case SILC_PKCS1_BT_PRV1:
+    /* Signature */
+    memset(dest_data + 2, bt == SILC_PKCS1_BT_PRV1 ? 0xff : 0x00, padlen);
+    break;
+
+  case SILC_PKCS1_BT_PUB:
+    /* Encryption */
+
+    /* It is guaranteed this routine does not return zero byte. */
+    if (rng)
+      for (i = 2; i < padlen; i++)
+       dest_data[i] = silc_rng_get_byte_fast(rng);
+    else
+      for (i = 2; i < padlen; i++)
+       dest_data[i] = silc_rng_global_get_byte_fast();
+    break;
+  }
+
+  /* Copy the data */
+  dest_data[padlen + 2] = 0x00;
+  memcpy(dest_data + padlen + 3, data, data_len);
+
+  return TRUE;
+}
+
+/* Decodes the PKCS#1 encoded block according to the block type `bt'.
+   When verifying signatures the `bt' must be SILC_PKCS1_BT_PRV1 and
+   when decrypting it must be SILC_PKCS1_BT_PUB.  This copies the
+   decoded data into `dest_data' which is size of `dest_data_size'.  If
+   the deocded block does not fit to `dest_data' this returns FALSE.
+   Returns TRUE on success. */
+
+bool silc_pkcs1_decode(SilcPkcs1BlockType bt,
+                      const unsigned char *data,
+                      SilcUInt32 data_len,
+                      unsigned char *dest_data,
+                      SilcUInt32 dest_data_size,
+                      SilcUInt32 *dest_len)
+{
+  int i = 0;
+
+  SILC_LOG_DEBUG(("PKCS#1 decoding, bt %d", bt));
+
+  /* Sanity checks */
+  if (!data || !dest_data || dest_data_size < 3 ||
+      data[0] != 0x00 || data[1] != (unsigned char)bt) {
+    SILC_LOG_DEBUG(("Malformed block"));
+    return FALSE;
+  }
+
+  /* Decode according to block type */
+  switch (bt) {
+  case SILC_PKCS1_BT_PRV0:
+    /* Do nothing */
+    break;
+
+  case SILC_PKCS1_BT_PRV1:
+    /* Verification */
+    for (i = 2; i < data_len; i++)
+      if (data[i] != 0xff)
+       break;
+    break;
+
+  case SILC_PKCS1_BT_PUB:
+    /* Decryption */
+    for (i = 2; i < data_len; i++)
+      if (data[i] == 0x00)
+       break;
+    break;
+  }
+
+  /* Sanity checks */
+  if (data[i++] != 0x00) {
+    SILC_LOG_DEBUG(("Malformed block"));
+    return FALSE;
+  }
+  if (i - 1 < SILC_PKCS1_MIN_PADDING) {
+    SILC_LOG_DEBUG(("Malformed block"));
+    return FALSE;
+  }
+  if (dest_data_size < data_len - i) {
+    SILC_LOG_DEBUG(("Destination buffer too small"));
+    return FALSE;
+  }
+
+  /* Copy the data */
+  memcpy(dest_data, data + i, data_len - i);
+
+  /* Return data length */
+  if (dest_len)
+    *dest_len = data_len - i;
+
+  return TRUE;
+}
diff --git a/lib/silccrypt/silcpkcs1.h b/lib/silccrypt/silcpkcs1.h
new file mode 100644 (file)
index 0000000..573777c
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+
+  silcpkcs1.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2003 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+/****h* silccrypt/SILC PKCS1 Interface
+ *
+ * DESCRIPTION
+ *
+ * This interface implements the PKCS#1 standard block encoding and decoding
+ * routines.  It is used as part of RSA implementation to perform PKCS#1
+ * RSA operations.  The routines encode and decode the data for RSA operations
+ * such as digital signatures and their verification, and encryption and
+ * decryption.
+ *
+ ***/
+
+#ifndef SILCPKCS1_H
+#define SILCPKCS1_H
+
+/****d* silccrypt/SilcPKCS1API/SilcPkcs1BlockType
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcPkcs1BlockType
+ *
+ * DESCRIPTION
+ *
+ *    Defines the PKCS#1 block types that define how the blcok is encoded
+ *    for different RSA operations.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_PKCS1_BT_PRV0 = 0x00,   /* Private key BT 0 */
+  SILC_PKCS1_BT_PRV1 = 0x01,   /* Private key BT 1 (use this always) */
+  SILC_PKCS1_BT_PUB  = 0x02,   /* Public key BT */
+} SilcPkcs1BlockType;
+/***/
+
+/****f* silccrypt/SilcPKCS1API/silc_pkcs1_encode
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_pkcs1_encode(SilcPkcs1BlockType bt,
+ *                           const unsigned char *data,
+ *                           SilcUInt32 data_len,
+ *                           unsigned char *dest_data,
+ *                           SilcUInt32 dest_data_size,
+ *                           SilcRng rng);
+ *
+ * DESCRIPTION
+ *
+ *    Encodes PKCS#1 data block from the `data' according to the block type
+ *    indicated by `bt'.  When encoding signatures the `bt' must be
+ *    SILC_PKCS1_BT_PRV1 and when encoding encryption blocks the `bt' must
+ *    be SILC_PKCS1_BT_PUB.  The encoded data is copied into the `dest_data'
+ *    buffer which is size of `dest_data_size'.  If the `dest_data' is not
+ *    able to hold the encoded block this returns FALSE.  Usually the
+ *    `dest_data_size' is set to the RSA key length value as it is the
+ *    length of one block.  The `rng' should be set when `bt' is set to
+ *    SILC_PKCS1_BT_PUB.  If `rng' is NULL global RNG is used.  This
+ *    function returns TRUE on success.
+ *
+ ***/
+bool silc_pkcs1_encode(SilcPkcs1BlockType bt,
+                      const unsigned char *data,
+                      SilcUInt32 data_len,
+                      unsigned char *dest_data,
+                      SilcUInt32 dest_data_size,
+                      SilcRng rng);
+
+/****f* silccrypt/SilcPKCS1API/silc_pkcs1_decode
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_pkcs1_decode(SilcPkcs1BlockType bt,
+ *                           const unsigned char *data,
+ *                           SilcUInt32 data_len,
+ *                           unsigned char *dest_data,
+ *                           SilcUInt32 dest_data_size,
+ *                           SilcUInt32 *dest_len);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes the PKCS#1 encoded block according to the block type `bt'.
+ *    When verifying signatures the `bt' must be SILC_PKCS1_BT_PRV1 and
+ *    when decrypting it must be SILC_PKCS1_BT_PUB.  This copies the
+ *    decoded data into `dest_data' which is size of `dest_data_size'.  If
+ *    the deocded block does not fit to `dest_data' this returns FALSE.
+ *    Returns the decoded length into `dest_len'.
+ *
+ ***/
+bool silc_pkcs1_decode(SilcPkcs1BlockType bt,
+                      const unsigned char *data,
+                      SilcUInt32 data_len,
+                      unsigned char *dest_data,
+                      SilcUInt32 dest_data_size,
+                      SilcUInt32 *dest_len);
+
+#endif /* SILCPKCS1_H */
index 48a3e0011ff755dc13dec26cb033f3ffe8164011..e62e58b7a90cf9311f0df091d463c0a9fddf219a 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcrng.c 
+  silcrng.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
  * Created: Sun Mar  9 00:09:18 1997
  *
  * The original RNG was based on Secure Shell's random number generator
- * by Tatu Ylönen and was used as reference when programming this RNG.  
+ * by Tatu Ylönen and was used as reference when programming this RNG.
  * This RNG has been rewritten twice since the creation.
  */
 
@@ -54,7 +54,7 @@ static void silc_rng_get_hard_noise(SilcRng rng);
 static void silc_rng_get_medium_noise(SilcRng rng);
 static void silc_rng_get_soft_noise(SilcRng rng);
 
-/* 
+/*
    SILC SilcRng State context.
 
    This object is used by the random number generator to provide
@@ -81,8 +81,8 @@ typedef struct SilcRngStateContext {
   struct SilcRngStateContext *next;
 } *SilcRngState;
 
-/* 
-   SILC Random Number Generator object. 
+/*
+   SILC Random Number Generator object.
 
    This object holds random pool which is used to generate the random
    numbers used by various routines needing cryptographically strong
@@ -179,7 +179,7 @@ void silc_rng_free(SilcRng rng)
   }
 }
 
-/* Initializes random number generator by getting noise from environment. 
+/* Initializes random number generator by getting noise from environment.
    The environmental noise is our so called seed. One should not call
    this function more than once. */
 
@@ -200,7 +200,7 @@ void silc_rng_init(SilcRng rng)
   first = rng->state;
   for (i = SILC_RNG_STATE_NUM - 1; i >= 1; i--) {
     next = silc_calloc(1, sizeof(*rng->state));
-    next->low = 
+    next->low =
       (i * (sizeof(rng->pool) / SILC_RNG_STATE_NUM));
     next->pos =
       (i * (sizeof(rng->pool) / SILC_RNG_STATE_NUM)) + 8;
@@ -229,7 +229,10 @@ static void silc_rng_get_soft_noise(SilcRng rng)
   struct tms ptime;
 #endif
   SilcUInt32 pos;
-  
+#ifdef HAVE_GETRUSAGE
+  struct rusage r;
+#endif
+
   pos = silc_rng_get_position(rng);
 
   silc_rng_xor(rng, clock(), 0);
@@ -277,7 +280,30 @@ static void silc_rng_get_soft_noise(SilcRng rng)
   silc_rng_xor(rng, getpgrp(), pos++);
 #endif
 #endif
-
+#ifdef HAVE_GETRUSAGE
+  getrusage(RUSAGE_SELF, &r);
+  silc_rng_xor(rng, (r.ru_utime.tv_sec + r.ru_utime.tv_usec), pos++);
+  silc_rng_xor(rng, (r.ru_utime.tv_sec ^ r.ru_utime.tv_usec), pos++);
+  silc_rng_xor(rng, (r.ru_stime.tv_sec + r.ru_stime.tv_usec), pos++);
+  silc_rng_xor(rng, (r.ru_stime.tv_sec ^ r.ru_stime.tv_usec), pos++);
+  silc_rng_xor(rng, (r.ru_maxrss + r.ru_ixrss), pos++);
+  silc_rng_xor(rng, (r.ru_maxrss ^ r.ru_ixrss), pos++);
+  silc_rng_xor(rng, (r.ru_idrss + r.ru_idrss), pos++);
+  silc_rng_xor(rng, (r.ru_idrss ^ r.ru_idrss), pos++);
+  silc_rng_xor(rng, (r.ru_idrss << 16), pos++);
+  silc_rng_xor(rng, (r.ru_minflt + r.ru_majflt), pos++);
+  silc_rng_xor(rng, (r.ru_minflt ^ r.ru_majflt), pos++);
+  silc_rng_xor(rng, (r.ru_nswap + r.ru_oublock + r.ru_inblock), pos++);
+  silc_rng_xor(rng, (r.ru_nswap << 8), pos++);
+  silc_rng_xor(rng, (r.ru_inblock + r.ru_oublock), pos++);
+  silc_rng_xor(rng, (r.ru_inblock ^ r.ru_oublock), pos++);
+  silc_rng_xor(rng, (r.ru_msgsnd ^ r.ru_msgrcv), pos++);
+  silc_rng_xor(rng, (r.ru_nsignals + r.ru_msgsnd + r.ru_msgrcv), pos++);
+  silc_rng_xor(rng, (r.ru_nsignals << 16), pos++);
+  silc_rng_xor(rng, (r.ru_nvcsw + r.ru_nivcsw), pos++);
+  silc_rng_xor(rng, (r.ru_nvcsw ^ r.ru_nivcsw), pos++);
+#endif
+  
 #ifdef SILC_RNG_DEBUG
   SILC_LOG_HEXDUMP(("pool"), rng->pool, sizeof(rng->pool));
 #endif
@@ -290,6 +316,10 @@ static void silc_rng_get_soft_noise(SilcRng rng)
 
 static void silc_rng_get_medium_noise(SilcRng rng)
 {
+  /* If getrusage is available, there is no need for shell commands */
+#ifdef HAVE_GETRUSAGE
+  return;
+#endif
   silc_rng_exec_command(rng, "ps -leaww 2> /dev/null");
   silc_rng_exec_command(rng, "ls -afiln ~ 2> /dev/null");
   silc_rng_exec_command(rng, "ls -afiln /proc 2> /dev/null");
@@ -308,7 +338,7 @@ static void silc_rng_get_hard_noise(SilcRng rng)
 #ifndef SILC_WIN32
   unsigned char buf[32];
   int fd, len, i;
-  
+
   /* Get noise from /dev/[u]random if available */
   fd = open(rng->devrandom, O_RDONLY);
   if (fd < 0)
@@ -342,22 +372,22 @@ static void silc_rng_exec_command(SilcRng rng, char *command)
   FILE *fd;
   int i;
   int c;
-  
+
   /* Open process */
   fd = popen(command, "r");
   if (!fd)
     return;
-  
+
   /* Get data as much as we can get into the buffer */
   for (i = 0; i < sizeof(buf); i++) {
     c = fgetc(fd);
     if (c == EOF)
-      break; 
+      break;
     buf[i] = c;
   }
-  
+
   pclose(fd);
-  
+
   if (i != 0) {
     /* Add the buffer into random pool */
     silc_rng_add_noise(rng, buf, i);
@@ -366,7 +396,7 @@ static void silc_rng_exec_command(SilcRng rng, char *command)
 #endif
 }
 
-/* This function adds the contents of the buffer as noise into random 
+/* This function adds the contents of the buffer as noise into random
    pool. After adding the noise the pool is stirred. */
 
 void silc_rng_add_noise(SilcRng rng, unsigned char *buffer, SilcUInt32 len)
@@ -397,7 +427,7 @@ static void silc_rng_xor(SilcRng rng, SilcUInt32 val, unsigned int pos)
   SILC_PUT32_MSB(val, &rng->pool[pos]);
 }
 
-/* This function stirs the random pool by encrypting buffer in CFB 
+/* This function stirs the random pool by encrypting buffer in CFB
    (cipher feedback) mode with SHA1 algorithm. */
 
 static void silc_rng_stir_pool(SilcRng rng)
@@ -483,7 +513,7 @@ static SilcUInt32 silc_rng_get_position(SilcRng rng)
     rng->state->pos = rng->state->low;
 
 #ifdef SILC_RNG_DEBUG
-    fprintf(stderr, "state: %p: low: %lu, pos: %lu\n", 
+    fprintf(stderr, "state: %p: low: %lu, pos: %lu\n",
            rng->state, rng->state->low, rng->state->pos);
 #endif
 
@@ -496,6 +526,8 @@ static SilcUInt32 silc_rng_get_position(SilcRng rng)
 
 SilcUInt8 silc_rng_get_byte(SilcRng rng)
 {
+  SilcUInt8 byte;
+
   rng->threshold++;
 
   /* Get more soft noise after 64 bits threshold */
@@ -508,7 +540,8 @@ SilcUInt8 silc_rng_get_byte(SilcRng rng)
     silc_rng_get_hard_noise(rng);
   }
 
-  return rng->pool[silc_rng_get_position(rng)];
+  do byte = rng->pool[silc_rng_get_position(rng)]; while (byte == 0x00);
+  return byte;
 }
 
 /* Return random byte as fast as possible. Reads from /dev/urandom if
@@ -529,7 +562,7 @@ SilcUInt8 silc_rng_get_byte_fast(SilcRng rng)
   if (read(rng->fd_devurandom, buf, sizeof(buf)) < 0)
     return silc_rng_get_byte(rng);
 
-  return buf[0];
+  return buf[0] != 0x00 ? buf[0] : silc_rng_get_byte(rng);
 #else
   return silc_rng_get_byte(rng);
 #endif
@@ -565,7 +598,7 @@ SilcUInt32 silc_rng_get_rn32(SilcRng rng)
   return num;
 }
 
-/* Returns random number string. Returned string is in HEX format. */
+/* Returns non-zero random number string. Returned string is in HEX format. */
 
 unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len)
 {
@@ -580,7 +613,7 @@ unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len)
   return string;
 }
 
-/* Returns random number binary data. */
+/* Returns non-zero random number binary data. */
 
 unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len)
 {
@@ -607,10 +640,13 @@ SilcRng global_rng = NULL;
 
 bool silc_rng_global_init(SilcRng rng)
 {
-  if (rng)
+  if (rng) {
     global_rng = rng;
-  else
-    global_rng = silc_rng_alloc();
+    return TRUE;
+  }
+
+  global_rng = silc_rng_alloc();
+  silc_rng_init(global_rng);
 
   return TRUE;
 }
index 7dbdcbf6a692655716b955db638ccb8893e36823..4ae6b7d8891fd089160a9d4e91c0e2dba308ef9f 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcrng.h 
+  silcrng.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@
 /****s* silccrypt/SilcRNGAPI/SilcRng
  *
  * NAME
- * 
+ *
  *    typedef struct SilcRngStruct *SilcRng;
  *
  * DESCRIPTION
@@ -174,7 +174,8 @@ SilcUInt32 silc_rng_get_rn32(SilcRng rng);
  * DESCRIPTION
  *
  *    Returns random string in HEX form of the length of `len' bytes.
- *    The caller must free returned data buffer.
+ *    The caller must free returned data buffer.  It is guaranteed the
+ *    data string goes not include any zero (0x00) bytes.
  *
  ***/
 unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len);
@@ -187,8 +188,9 @@ unsigned char *silc_rng_get_rn_string(SilcRng rng, SilcUInt32 len);
  *
  * DESCRIPTION
  *
- *    Returns random binary data of the length of `len' bytes.  The 
- *    caller must free returned data buffer.
+ *    Returns random binary data of the length of `len' bytes.  The
+ *    caller must free returned data buffer.  It is guaranteed the data
+ *    buffer does not include any zero (0x00) bytes.
  *
  ***/
 unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len);
@@ -201,7 +203,7 @@ unsigned char *silc_rng_get_rn_data(SilcRng rng, SilcUInt32 len);
  *
  * DESCRIPTION
  *
- *    Add the data buffer indicated by `buffer' of length of `len' bytes 
+ *    Add the data buffer indicated by `buffer' of length of `len' bytes
  *    as noise to the random number generator.  The random number generator
  *    is restirred (reseeded) when this function is called.
  *
@@ -317,7 +319,8 @@ SilcUInt32 silc_rng_global_get_rn32(void);
  * DESCRIPTION
  *
  *    Returns random string in HEX form of the length of `len' bytes.
- *    The caller must free returned data buffer.
+ *    The caller must free returned data buffer.  It is guaranteed the
+ *    data string goes not include any zero (0x00) bytes.
  *
  ***/
 unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len);
@@ -330,8 +333,9 @@ unsigned char *silc_rng_global_get_rn_string(SilcUInt32 len);
  *
  * DESCRIPTION
  *
- *    Returns random binary data of the length of `len' bytes.  The 
- *    caller must free returned data buffer.
+ *    Returns random binary data of the length of `len' bytes.  The
+ *    caller must free returned data buffer.  It is guaranteed the data
+ *    buffer does not include any zero (0x00) bytes.
  *
  ***/
 unsigned char *silc_rng_global_get_rn_data(SilcUInt32 len);
@@ -344,7 +348,7 @@ unsigned char *silc_rng_global_get_rn_data(SilcUInt32 len);
  *
  * DESCRIPTION
  *
- *    Add the data buffer indicated by `buffer' of length of `len' bytes 
+ *    Add the data buffer indicated by `buffer' of length of `len' bytes
  *    as noise to the random number generator.  The random number generator
  *    is restirred (reseeded) when this function is called.
  *
index e2aa13178ae8660290ad9f59632a6737caab48b0..1fd793a91f789c3565edf8b51222e85d8782be1e 100644 (file)
@@ -3,7 +3,7 @@
 #
 #  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2002 Pekka Riikonen
+#  Copyright (C) 2002 - 2003 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
@@ -22,7 +22,8 @@ bin_PROGRAMS =        test_sha1       \
                test_hmacsha1   \
                test_hmacmd5    \
                test_aes        \
-               test_twofish
+               test_twofish    \
+               test_silcpkcs
 
 test_sha1_SOURCES = test_sha1.c
 test_md5_SOURCES = test_md5.c
@@ -32,6 +33,8 @@ test_hmacmd5_SOURCES = test_hmacmd5.c
 test_aes_SOURCES = test_aes.c
 test_twofish_SOURCES = test_aes.c
 
+test_silcpkcs_SOURCES = test_silcpkcs.c
+
 LIBS = $(SILC_COMMON_LIBS)
 LDADD = -L.. -L../.. -lsilc
 
diff --git a/lib/silccrypt/tests/test_silcpkcs.c b/lib/silccrypt/tests/test_silcpkcs.c
new file mode 100644 (file)
index 0000000..b1c2354
--- /dev/null
@@ -0,0 +1,309 @@
+/* Tests API in silcpkcs.h */
+#include "silcincludes.h"
+
+int key_len = 2048;
+const unsigned char p[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
+int p_len = 32;
+
+int test()
+{
+  bool success = FALSE;
+  SilcPKCS pkcs;
+  unsigned char *pk, *prv;
+  char *identifier;
+  SilcUInt32 pk_len = 0, prv_len = 0;
+  SilcPublicKey pubkey, pubkey2;
+  SilcPublicKeyIdentifier ident;
+  SilcPrivateKey privkey;
+  SilcBuffer buf;
+  unsigned char d[4096], d2[4096];
+  SilcUInt32 dlen, d2len;
+  SilcHash sha1;
+
+  SILC_LOG_DEBUG(("Registering PKCSs"));
+  if (!silc_pkcs_register_default()) {
+    SILC_LOG_DEBUG(("Registering PKCSs failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Supported PKCS: %s", silc_pkcs_get_supported()));
+
+
+  SILC_LOG_DEBUG(("Allocate rsa PKCS"));
+  if (!silc_pkcs_is_supported("rsa")) {
+    SILC_LOG_DEBUG(("rsa PKCS not supported"));
+    goto err;
+  }
+  if (!silc_pkcs_alloc("rsa", &pkcs)) {
+    SILC_LOG_DEBUG(("Allocate rsa PKCS failed"));
+    goto err;
+  }
+
+
+  SILC_LOG_DEBUG(("Generating new key pair"));
+  if (!silc_pkcs_generate_key(pkcs, key_len, NULL)) {
+    SILC_LOG_DEBUG(("Generating new key pair failed"));
+    goto err;
+  }
+
+
+  SILC_LOG_DEBUG(("Key length: %d", silc_pkcs_get_key_len(pkcs)));
+  if (silc_pkcs_get_key_len(pkcs) != key_len) {
+    SILC_LOG_DEBUG(("Bad key length: %d != %d",
+                   silc_pkcs_get_key_len(pkcs), key_len));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("PKCS name: %s", silc_pkcs_get_name(pkcs)));
+
+  SILC_LOG_DEBUG(("------"));
+  SILC_LOG_DEBUG(("------ Testing Public Key Routines"));
+  SILC_LOG_DEBUG(("------"));
+
+  SILC_LOG_DEBUG(("Get public key from PKCS"));
+  pk = silc_pkcs_get_public_key(pkcs, &pk_len);
+  if (!pk || !pk_len) {
+    SILC_LOG_DEBUG(("Getting public key failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Making new public key identifier"));
+  identifier = silc_pkcs_encode_identifier("foo", "bar", "foo bar",
+                                          "foo@bar.com", "bar", "BB");
+  if (!identifier) {
+    SILC_LOG_DEBUG(("Making new public key identifier failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decoding public key identifier"));
+  ident = silc_pkcs_decode_identifier(identifier);
+  if (!ident) {
+    SILC_LOG_DEBUG(("Decoding public key identifier failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Allocating SilcPublicKey"));
+  pubkey = silc_pkcs_public_key_alloc("rsa", identifier, pk, pk_len);
+  if (!pubkey) {
+    SILC_LOG_DEBUG(("Allocating SilcPublicKey failed"));
+    goto err;
+  }
+  silc_free(pk);
+  SILC_LOG_DEBUG(("Encode SilcPublicKey data"));
+  pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
+  if (!pk) {
+    SILC_LOG_DEBUG(("Encode SilcPublicKey data failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decode public key to SilcPublicKey"));
+  if (!silc_pkcs_public_key_decode(pk, pk_len, &pubkey)) {
+    SILC_LOG_DEBUG(("Decode public key to SilcPublicKey failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Save public key to publickey.pub"));
+  unlink("publickey.pub");
+  if (!silc_pkcs_save_public_key("publickey.pub", pubkey,
+                                SILC_PKCS_FILE_PEM)) {
+    SILC_LOG_DEBUG(("Save public key to publickey.pub failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Copying public key"));
+  pubkey2 = silc_pkcs_public_key_copy(pubkey);
+  if (!pubkey2) {
+    SILC_LOG_DEBUG(("Copying public key failed"));
+    goto err;
+  }
+  silc_pkcs_public_key_free(pubkey);
+  SILC_LOG_DEBUG(("Load public key"));
+  if (!silc_pkcs_load_public_key("publickey.pub", &pubkey,
+                                SILC_PKCS_FILE_PEM)) {
+    SILC_LOG_DEBUG(("Load public key failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Comparing copied and loaded public keys"));
+  if (!silc_pkcs_public_key_compare(pubkey, pubkey2)) {
+    SILC_LOG_DEBUG(("Comparing copied and loaded public keys failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Match"));
+  SILC_LOG_DEBUG(("Set public key to PKCS"));
+  if (!silc_pkcs_public_key_set(pkcs, pubkey)) {
+    SILC_LOG_DEBUG(("Set public key to PKCS"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Encoding public key payload"));
+  buf = silc_pkcs_public_key_payload_encode(pubkey);
+  if (!buf) {
+    SILC_LOG_DEBUG(("Encoding public key payload failed"));
+    goto err;
+  }
+  silc_pkcs_public_key_free(pubkey2);
+  SILC_LOG_DEBUG(("Decoding public key payload"));
+  if (!silc_pkcs_public_key_payload_decode(buf->data, buf->len, &pubkey2)) {
+    SILC_LOG_DEBUG(("Decoding public key payload failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Comparing decoded and original public keys"));
+  if (!silc_pkcs_public_key_compare(pubkey2, pubkey)) {
+    SILC_LOG_DEBUG(("Comparing decoded and original public keys failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Match"));
+  SILC_LOG_DEBUG(("Dumping public key identifier"));
+  silc_show_public_key("publickey.pub");
+  unlink("publickey.pub");
+  silc_free(pk);
+  silc_free(identifier);
+  silc_pkcs_free_identifier(ident);
+  silc_pkcs_public_key_free(pubkey);
+  silc_pkcs_public_key_free(pubkey2);
+
+
+  SILC_LOG_DEBUG(("------"));
+  SILC_LOG_DEBUG(("------ Testing Private Key Routines"));
+  SILC_LOG_DEBUG(("------"));
+
+  SILC_LOG_DEBUG(("Get private key from PKCS"));
+  prv = silc_pkcs_get_private_key(pkcs, &prv_len);
+  if (!prv || !prv_len) {
+    SILC_LOG_DEBUG(("Getting private key failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Allocating SilcPrivateKey"));
+  privkey = silc_pkcs_private_key_alloc("rsa", prv, prv_len);
+  if (!privkey) {
+    SILC_LOG_DEBUG(("Allocating SilcPrivateKey failed"));
+    goto err;
+  }
+  silc_free(prv);
+  SILC_LOG_DEBUG(("Encode SilcPrivateKey data"));
+  prv = silc_pkcs_private_key_encode(privkey, &prv_len);
+  if (!prv) {
+    SILC_LOG_DEBUG(("Encode SilcPrivateKey data failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decode private key to SilcPrivateKey"));
+  if (!silc_pkcs_private_key_decode(prv, prv_len, &privkey)) {
+    SILC_LOG_DEBUG(("Decode private key to SilcPrivateKey failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Save private key to privkey.prv"));
+  unlink("privkey.prv");
+  if (!silc_pkcs_save_private_key("privkey.prv", privkey,
+                                 "foobar", 6,
+                                 SILC_PKCS_FILE_BIN)) {
+    SILC_LOG_DEBUG(("Save private key to priv.pub failed"));
+    goto err;
+  }
+  silc_pkcs_private_key_free(privkey);
+  SILC_LOG_DEBUG(("Load private key"));
+  if (!silc_pkcs_load_private_key("privkey.prv", &privkey, "foobar", 6,
+                                 SILC_PKCS_FILE_BIN)) {
+    SILC_LOG_DEBUG(("Load private key failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Set private key to PKCS"));
+  if (!silc_pkcs_private_key_set(pkcs, privkey)) {
+    SILC_LOG_DEBUG(("Set private key to PKCS"));
+    goto err;
+  }
+  unlink("privkey.prv");
+  silc_free(prv);
+  silc_pkcs_private_key_free(privkey);
+
+
+  SILC_LOG_DEBUG(("------"));
+  SILC_LOG_DEBUG(("------ Testing Public Key Cryptography Operations"));
+  SILC_LOG_DEBUG(("------"));
+
+  memset(d, 0, sizeof(d));
+  memset(d2, 0, sizeof(d2));
+
+  SILC_LOG_DEBUG(("Encrypting data"));
+  if (!silc_pkcs_encrypt(pkcs, (unsigned char *)p, p_len, d, &dlen)) {
+    SILC_LOG_DEBUG(("Encrypting data failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decrypting data"));
+  if (!silc_pkcs_decrypt(pkcs, d, dlen, d2, &d2len)) {
+    SILC_LOG_DEBUG(("Decrypting data failed"));
+    goto err;
+  }
+  SILC_LOG_HEXDUMP(("Plaintext"), p, p_len);
+  SILC_LOG_HEXDUMP(("Ciphertext"), d, dlen);
+  SILC_LOG_HEXDUMP(("Decrypted"), d2, d2len);
+  if (memcmp(p, d2, p_len)) {
+    SILC_LOG_DEBUG(("Decryption failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Decryption successful"));
+  memset(d, 0, sizeof(d));
+  memset(d2, 0, sizeof(d2));
+
+  SILC_LOG_DEBUG(("Signing data"));
+  if (!silc_pkcs_sign(pkcs, (unsigned char *)p, p_len, d, &dlen)) {
+    SILC_LOG_DEBUG(("Signing data failed"));
+    goto err;
+  }
+  SILC_LOG_HEXDUMP(("Data"), p, p_len);
+  SILC_LOG_HEXDUMP(("signature"), d, dlen);
+  SILC_LOG_DEBUG(("Verifying data"));
+  if (!silc_pkcs_verify(pkcs, d, dlen, (unsigned char *)p, p_len)) {
+    SILC_LOG_DEBUG(("Verifying data failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Verification successful"));
+
+  silc_hash_alloc("sha1", &sha1);
+  SILC_LOG_DEBUG(("Signing data with hash"));
+  if (!silc_pkcs_sign_with_hash(pkcs, sha1, (unsigned char *)p, p_len,
+                               d, &dlen)) {
+    SILC_LOG_DEBUG(("Signing data with hash failed"));
+    goto err;
+  }
+  SILC_LOG_HEXDUMP(("Data"), p, p_len);
+  SILC_LOG_HEXDUMP(("signature"), d, dlen);
+  SILC_LOG_DEBUG(("Verifying data with hash"));
+  if (!silc_pkcs_verify_with_hash(pkcs, sha1, d, dlen,
+                                 (unsigned char *)p, p_len)) {
+    SILC_LOG_DEBUG(("Verifying data with hash failed"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("Verification with hash successful"));
+  silc_hash_free(sha1);
+
+  silc_pkcs_free(pkcs);
+  success = TRUE;
+
+ err:
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}
+
+int main(int argc, char **argv)
+{
+  int success;
+  int i;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_debug = 1;
+    silc_debug_hexdump = 1;
+    silc_log_set_debug_string("*crypt*,*pkcs*,*rsa*,*primegen*");
+  }
+  silc_hash_register_default();
+  silc_hmac_register_default();
+  silc_cipher_register_default();
+  silc_rng_global_init(NULL);
+
+  success = test();
+
+  for (i = 0; i < 100; i++) {
+    success = test();
+    if (!success)
+      break;
+  }
+
+  silc_pkcs_unregister_all();
+  silc_hash_unregister_all();
+  silc_hmac_unregister_all();
+  silc_cipher_unregister_all();
+
+  return success;
+}
similarity index 75%
rename from lib/silcmath/Makefile.am
rename to lib/silcmath/Makefile.ad
index 4dec62ac8500d3c05e8ac9cd65827e357d2b64f8..a65c9d88f9dceb8e777f30e090eb39172868001e 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -24,18 +23,14 @@ else
 SUBDIRS =
 endif
 
+DIST_SUBDIRS = mpi
+
 noinst_LTLIBRARIES = libsilcmath.la
 
 if SILC_MP_NSS_MPI
 MP_SOURCE = mp_mpi.c
-if SILC_DIST_TOOLKIT
-MP_HEADER = mpi/mpi.h mpi/mplogic.h mpi/mpi-config.h
-else
-MP_HEADER =
-endif
 else
 MP_SOURCE = mp_gmp.c
-MP_HEADER =
 endif
 
 libsilcmath_la_SOURCES = \
@@ -44,14 +39,15 @@ libsilcmath_la_SOURCES = \
        mpbin.c \
        $(MP_SOURCE)
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
+MP_HEADER = mpi/mpi.h mpi/mplogic.h mpi/mpi-config.h
 include_HEADERS =      \
        mp_gmp.h        \
        mp_mpi.h        \
        silcmath.h      \
        silcmp.h        \
        $(MP_HEADER)
-endif
+#endif SILC_DIST_TOOLKIT
 
 EXTRA_DIST = mp_gmp.c mp_mpi.c *.h
 
index ee5e02389569a7ceaced028d3b856e1652f9872a..4a6cc6b354c5945478e8169edb2ee760e2c149e5 100644 (file)
@@ -14,7 +14,7 @@
 <b>Introduction</b>
 
 <br /><br />
-SILC SFTP Library provides SSH File Transfer Protocol client and server
+SILC SFTP Library provides Secure File Transfer Protocol client and server
 implementation.  The SFTP protocol is the mandatory file transfer protocol
 used for file transfers in the SILC protocol.  The same interface is used
 for SFTP client and SFTP server.
similarity index 76%
rename from lib/silcsftp/Makefile.am
rename to lib/silcsftp/Makefile.ad
index 1d0932975eff50b02554022531ef93dfaed0fdab..de35d2ad2494057fec0eb5f28b6c22f2a1c3738e 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
 #  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2001 Pekka Riikonen
+#  Copyright (C) 2001 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -26,12 +25,14 @@ libsilcsftp_la_SOURCES =    \
        sftp_util.c             \
        sftp_fs_memory.c
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS =      \
        silcsftp.h      \
        silcsftp_fs.h
-endif
 
-EXTRA_DIST = *.h tests
+SILC_EXTRA_DIST = tests
+#endif SILC_DIST_TOOLKIT
+
+EXTRA_DIST = *.h $(SILC_EXTRA_DIST)
 
 include $(top_srcdir)/Makefile.defines.in
index 708885ba87495c41cf0de1e5fe5bafd78bb01296..1b198b860f689488be8b7544deb01fb1f37d786c 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_client.c 
+  sftp_client.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -84,7 +84,7 @@ static void silc_sftp_handle_delete(SilcSFTPHandle handle)
 
 /* Returns the handle data of the `handle' to the `data' pointer. */
 
-static void silc_sftp_handle_get(SilcSFTPHandle handle, 
+static void silc_sftp_handle_get(SilcSFTPHandle handle,
                                 const unsigned char **data,
                                 SilcUInt32 *data_len)
 {
@@ -95,7 +95,7 @@ static void silc_sftp_handle_get(SilcSFTPHandle handle,
 /* General routine to send SFTP packet to the SFTP server. */
 
 static void silc_sftp_send_packet(SilcSFTPClient sftp,
-                                 SilcSFTPPacket type, 
+                                 SilcSFTPPacket type,
                                  SilcUInt32 len, ...)
 {
   SilcBuffer tmp;
@@ -108,7 +108,7 @@ static void silc_sftp_send_packet(SilcSFTPClient sftp,
     return;
   sftp->packet = tmp;
 
-  SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data, 
+  SILC_LOG_HEXDUMP(("SFTP packet to server"), sftp->packet->data,
                   sftp->packet->len);
 
   /* Send the packet */
@@ -143,8 +143,8 @@ static SilcSFTPRequest silc_sftp_find_request(SilcSFTPClient sftp, SilcUInt32 id
    operation. The variable argument list includes the status and req->type
    specific data. */
 
-static void silc_sftp_call_request(SilcSFTPClient sftp, 
-                                  SilcSFTPRequest req, 
+static void silc_sftp_call_request(SilcSFTPClient sftp,
+                                  SilcSFTPRequest req,
                                   SilcSFTPPacket type,
                                   SilcSFTPStatus status, ...)
 {
@@ -171,9 +171,9 @@ static void silc_sftp_call_request(SilcSFTPClient sftp,
       data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
 
       if (req->data)
-       (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data, 
+       (*req->data)((SilcSFTP)sftp, status, (const unsigned char *)data,
                     data_len, req->context);
-    }    
+    }
     break;
 
   case SILC_SFTP_OPEN:
@@ -221,7 +221,7 @@ static void silc_sftp_call_request(SilcSFTPClient sftp,
       language_tag = (char *)va_arg(vp, char *);
 
       if (req->status)
-       (*req->status)((SilcSFTP)sftp, status, (const char *)message, 
+       (*req->status)((SilcSFTP)sftp, status, (const char *)message,
                       (const char *)language_tag, req->context);
     }
     break;
@@ -242,7 +242,7 @@ static void silc_sftp_call_request(SilcSFTPClient sftp,
       attr = (SilcSFTPAttributes)va_arg(vp, SilcSFTPAttributes);
 
       if (req->attr)
-       (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr, 
+       (*req->attr)((SilcSFTP)sftp, status, (const SilcSFTPAttributes)attr,
                     req->context);
     }
     break;
@@ -283,7 +283,7 @@ static void silc_sftp_call_request(SilcSFTPClient sftp,
       data_len = (SilcUInt32)va_arg(vp, SilcUInt32);
 
       if (req->extended)
-       (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data, 
+       (*req->extended)((SilcSFTP)sftp, status, (const unsigned char *)data,
                         data_len, req->context);
     }
     break;
@@ -302,7 +302,7 @@ static void silc_sftp_call_request(SilcSFTPClient sftp,
 /* Starts SFTP client and returns context for it.  The version callback
    indicated by the `callback' will be called after the SFTP session has
    been started and server has returned the version of the protocol.  The
-   SFTP client context is returned in the callback too.  This returns 
+   SFTP client context is returned in the callback too.  This returns
    allocated SFTP client context or NULL on error. */
 
 SilcSFTP silc_sftp_client_start(SilcSFTPSendPacketCallback send_packet,
@@ -325,7 +325,7 @@ SilcSFTP silc_sftp_client_start(SilcSFTPSendPacketCallback send_packet,
   silc_list_init(sftp->requests, struct SilcSFTPRequestStruct, next);
 
   /* Send the SFTP session initialization to the server */
-  silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4, 
+  silc_sftp_send_packet(sftp, SILC_SFTP_INIT, 4,
                        SILC_STR_UI_INT(SILC_SFTP_PROTOCOL_VERSION),
                        SILC_STR_END);
 
@@ -365,7 +365,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
   SILC_LOG_DEBUG(("Start"));
 
   /* Parse the packet */
-  type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload, 
+  type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
                                 &payload_len);
   if (!type)
     return;
@@ -383,13 +383,13 @@ void silc_sftp_client_receive_process(SilcSFTP context,
                                 SILC_STR_UI_INT(&version),
                                 SILC_STR_END);
       if (ret < 0) {
-       (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0, 
+       (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_FAILURE, 0,
                         sftp->version_context);
        break;
       }
 
       /* Call the callback */
-      (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version, 
+      (*sftp->version)((SilcSFTP)sftp, SILC_SFTP_STATUS_OK, version,
                       sftp->version_context);
     }
     break;
@@ -401,7 +401,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
 
       SILC_LOG_DEBUG(("Status packet"));
 
-      ret = silc_buffer_unformat(&buf, 
+      ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
                                 SILC_STR_UI_INT(&status),
                                 SILC_STR_END);
@@ -443,9 +443,9 @@ void silc_sftp_client_receive_process(SilcSFTP context,
 
       SILC_LOG_DEBUG(("Handle packet"));
 
-      ret = silc_buffer_unformat(&buf, 
+      ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&handle, 
+                                SILC_STR_UI32_NSTRING(&handle,
                                                       &handle_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -457,7 +457,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
        break;
 
       /* Call the callback */
-      silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, 
+      silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
                             handle, handle_len);
     }
     break;
@@ -469,7 +469,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
 
       SILC_LOG_DEBUG(("Data packet"));
 
-      ret = silc_buffer_unformat(&buf, 
+      ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
                                 SILC_STR_UI32_NSTRING(&data, &data_len),
                                 SILC_STR_END);
@@ -482,7 +482,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
        break;
 
       /* Call the callback */
-      silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, 
+      silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
                             data, data_len);
     }
     break;
@@ -494,7 +494,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
 
       SILC_LOG_DEBUG(("Name packet"));
 
-      ret = silc_buffer_unformat(&buf, 
+      ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
                                 SILC_STR_UI_INT(&count),
                                 SILC_STR_END);
@@ -526,7 +526,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
 
       SILC_LOG_DEBUG(("Attributes packet"));
 
-      ret = silc_buffer_unformat(&buf, 
+      ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
                                 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
                                 SILC_STR_END);
@@ -554,7 +554,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
 
       SILC_LOG_DEBUG(("Extended reply packet"));
 
-      ret = silc_buffer_unformat(&buf, 
+      ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
                                 SILC_STR_UI_XNSTRING(&data, buf.len - 4),
                                 SILC_STR_END);
@@ -567,7 +567,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
        break;
 
       /* Call the callback */
-      silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK, 
+      silc_sftp_call_request(sftp, req, type, SILC_SFTP_STATUS_OK,
                             data, buf.len - 4);
     }
     break;
@@ -577,7 +577,7 @@ void silc_sftp_client_receive_process(SilcSFTP context,
   }
 }
 
-void silc_sftp_open(SilcSFTP sftp, 
+void silc_sftp_open(SilcSFTP sftp,
                    const char *filename,
                    SilcSFTPFileOperation pflags,
                    SilcSFTPAttributes attrs,
@@ -605,12 +605,12 @@ void silc_sftp_open(SilcSFTP sftp,
     return;
   len = 4 + 4 + strlen(filename) + 4 + attrs_buf->len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(filename)),
                        SILC_STR_UI32_STRING(filename),
                        SILC_STR_UI_INT(pflags),
-                       SILC_STR_UI_XNSTRING(attrs_buf->data, 
+                       SILC_STR_UI_XNSTRING(attrs_buf->data,
                                             attrs_buf->len),
                        SILC_STR_END);
 
@@ -642,16 +642,17 @@ void silc_sftp_close(SilcSFTP sftp,
   silc_sftp_handle_get(handle, &hdata, &hdata_len);
   len = 4 + 4 + hdata_len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(hdata_len),
                        SILC_STR_UI_XNSTRING(hdata, hdata_len),
                        SILC_STR_END);
+  silc_sftp_handle_delete(handle);
 }
 
 void silc_sftp_read(SilcSFTP sftp,
                    SilcSFTPHandle handle,
-                   SilcUInt64 offset, 
+                   SilcUInt64 offset,
                    SilcUInt32 len,
                    SilcSFTPDataCallback callback,
                    void *context)
@@ -676,7 +677,7 @@ void silc_sftp_read(SilcSFTP sftp,
   silc_sftp_handle_get(handle, &hdata, &hdata_len);
   len2 = 4 + 4 + hdata_len + 8 + 4;
 
-  silc_sftp_send_packet(client, req->type, len2, 
+  silc_sftp_send_packet(client, req->type, len2,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(hdata_len),
                        SILC_STR_UI_XNSTRING(hdata, hdata_len),
@@ -713,7 +714,7 @@ void silc_sftp_write(SilcSFTP sftp,
   silc_sftp_handle_get(handle, &hdata, &hdata_len);
   len = 4 + 4 + hdata_len + 8 + 4 + data_len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(hdata_len),
                        SILC_STR_UI_XNSTRING(hdata, hdata_len),
@@ -745,7 +746,7 @@ void silc_sftp_remove(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(filename);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(filename)),
                        SILC_STR_UI32_STRING(filename),
@@ -775,7 +776,7 @@ void silc_sftp_rename(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(oldname) + 4 + strlen(newname);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(oldname)),
                        SILC_STR_UI32_STRING(oldname),
@@ -811,7 +812,7 @@ void silc_sftp_mkdir(SilcSFTP sftp,
     return;
   len = 4 + 4 + strlen(path) + attrs_buf->len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -844,7 +845,7 @@ void silc_sftp_rmdir(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(path);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -873,7 +874,7 @@ void silc_sftp_opendir(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(path);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -905,7 +906,7 @@ void silc_sftp_readdir(SilcSFTP sftp,
   silc_sftp_handle_get(handle, &hdata, &hdata_len);
   len = 4 + 4 + hdata_len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(hdata_len),
                        SILC_STR_UI_XNSTRING(hdata, hdata_len),
@@ -934,7 +935,7 @@ void silc_sftp_stat(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(path);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -963,7 +964,7 @@ void silc_sftp_lstat(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(path);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -995,7 +996,7 @@ void silc_sftp_fstat(SilcSFTP sftp,
   silc_sftp_handle_get(handle, &hdata, &hdata_len);
   len = 4 + 4 + hdata_len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(hdata_len),
                        SILC_STR_UI_XNSTRING(hdata, hdata_len),
@@ -1029,7 +1030,7 @@ void silc_sftp_setstat(SilcSFTP sftp,
     return;
   len = 4 + 4 + strlen(path) + attrs_buf->len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -1070,7 +1071,7 @@ void silc_sftp_fsetstat(SilcSFTP sftp,
     return;
   len = 4 + 4 + hdata_len + attrs_buf->len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(hdata_len),
                        SILC_STR_UI_XNSTRING(hdata, hdata_len),
@@ -1103,7 +1104,7 @@ void silc_sftp_readlink(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(path);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -1133,7 +1134,7 @@ void silc_sftp_symlink(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(linkpath) + 4 + strlen(targetpath);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(linkpath)),
                        SILC_STR_UI32_STRING(linkpath),
@@ -1164,7 +1165,7 @@ void silc_sftp_realpath(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(path);
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(path)),
                        SILC_STR_UI32_STRING(path),
@@ -1195,7 +1196,7 @@ void silc_sftp_extended(SilcSFTP sftp,
 
   len = 4 + 4 + strlen(request) + data_len;
 
-  silc_sftp_send_packet(client, req->type, len, 
+  silc_sftp_send_packet(client, req->type, len,
                        SILC_STR_UI_INT(req->id),
                        SILC_STR_UI_INT(strlen(request)),
                        SILC_STR_UI32_STRING(request),
index 7d1cba04679135ddc7045332c9329b99f434e801..b91e212ec5639146b0bcbd7fe985317bb52dcb8b 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_fs_memory.c 
+  sftp_fs_memory.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -76,8 +76,8 @@ static bool mem_add_entry(MemFSEntry dir, MemFSEntry entry,
   int i;
 
   /* Must be both write and exec permissions */
-  if (check_perm && 
-      !((dir->perm & SILC_SFTP_FS_PERM_WRITE) && 
+  if (check_perm &&
+      !((dir->perm & SILC_SFTP_FS_PERM_WRITE) &&
        (dir->perm & SILC_SFTP_FS_PERM_EXEC)))
     return FALSE;
 
@@ -150,7 +150,7 @@ static bool mem_del_entry(MemFSEntry entry, bool check_perm)
   return TRUE;
 }
 
-/* Finds first occurence of entry named `name' under the directory `dir'. 
+/* Finds first occurence of entry named `name' under the directory `dir'.
    This does not check subdirectories recursively. */
 
 static MemFSEntry mem_find_entry(MemFSEntry dir, const char *name,
@@ -458,7 +458,7 @@ bool silc_sftp_fs_memory_del_file(SilcSFTPFilesystem fs, void *dir,
   if (!filename)
     return FALSE;
 
-  return mem_del_entry_name(dir ? dir : memfs->root, filename, 
+  return mem_del_entry_name(dir ? dir : memfs->root, filename,
                            strlen(filename), FALSE);
 }
 
@@ -492,7 +492,7 @@ unsigned char *mem_encode_handle(void *context, SilcSFTP sftp,
   return data;
 }
 
-void mem_open(void *context, SilcSFTP sftp, 
+void mem_open(void *context, SilcSFTP sftp,
              const char *filename,
              SilcSFTPFileOperation pflags,
              SilcSFTPAttributes attrs,
@@ -520,20 +520,20 @@ void mem_open(void *context, SilcSFTP sftp,
   if (entry->directory || !entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Check for reading */
-  if ((pflags & SILC_SFTP_FXF_READ) && 
+  if ((pflags & SILC_SFTP_FXF_READ) &&
       !(entry->perm & SILC_SFTP_FS_PERM_READ)) {
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
     return;
-  }    
+  }
 
   /* Check for writing */
-  if (((pflags & SILC_SFTP_FXF_WRITE) || (pflags & SILC_SFTP_FXF_APPEND)) && 
+  if (((pflags & SILC_SFTP_FXF_WRITE) || (pflags & SILC_SFTP_FXF_APPEND)) &&
       !(entry->perm & SILC_SFTP_FS_PERM_WRITE)) {
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
     return;
   }
@@ -548,7 +548,7 @@ void mem_open(void *context, SilcSFTP sftp,
     flags |= O_APPEND;
 
   /* Attempt to open the file for real. */
-  fd = silc_file_open_mode(entry->data + 7, flags, 
+  fd = silc_file_open_mode(entry->data + 7, flags,
                           (attrs->flags & SILC_SFTP_ATTR_PERMISSIONS ?
                            attrs->permissions : 0600));
   if (fd == -1) {
@@ -559,10 +559,10 @@ void mem_open(void *context, SilcSFTP sftp,
   /* File opened, return handle */
   handle = mem_create_handle(fs, fd, entry);
   if (handle)
-    (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle, 
+    (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle,
                callback_context);
   else
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
 }
 
@@ -578,7 +578,7 @@ void mem_close(void *context, SilcSFTP sftp,
   if (h->fd != -1) {
     ret = silc_file_close(h->fd);
     if (ret == -1) {
-      (*callback)(sftp, silc_sftp_map_errno(errno), NULL, NULL, 
+      (*callback)(sftp, silc_sftp_map_errno(errno), NULL, NULL,
                  callback_context);
       return;
     }
@@ -590,7 +590,7 @@ void mem_close(void *context, SilcSFTP sftp,
 
 void mem_read(void *context, SilcSFTP sftp,
              SilcSFTPHandle handle,
-             SilcUInt64 offset, 
+             SilcUInt64 offset,
              SilcUInt32 len,
              SilcSFTPDataCallback callback,
              void *callback_context)
@@ -621,7 +621,7 @@ void mem_read(void *context, SilcSFTP sftp,
   }
 
   /* Return data */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const unsigned char *)data, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const unsigned char *)data,
              ret, callback_context);
 
   silc_free(data);
@@ -643,7 +643,7 @@ void mem_write(void *context, SilcSFTP sftp,
   /* Attempt to write */
   ret = silc_file_write(h->fd, data, data_len);
   if (ret <= 0) {
-    (*callback)(sftp, silc_sftp_map_errno(errno), NULL, NULL, 
+    (*callback)(sftp, silc_sftp_map_errno(errno), NULL, NULL,
                callback_context);
     return;
   }
@@ -657,7 +657,7 @@ void mem_remove(void *context, SilcSFTP sftp,
                void *callback_context)
 {
   /* Remove is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
@@ -668,7 +668,7 @@ void mem_rename(void *context, SilcSFTP sftp,
                void *callback_context)
 {
   /* Rename is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
@@ -679,7 +679,7 @@ void mem_mkdir(void *context, SilcSFTP sftp,
               void *callback_context)
 {
   /* Mkdir is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
@@ -689,7 +689,7 @@ void mem_rmdir(void *context, SilcSFTP sftp,
               void *callback_context)
 {
   /* Rmdir is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
@@ -715,11 +715,11 @@ void mem_opendir(void *context, SilcSFTP sftp,
   if (!entry->directory) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Must be read permissions to open a directory */
   if (!(entry->perm & SILC_SFTP_FS_PERM_READ)) {
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
     return;
   }
@@ -727,10 +727,10 @@ void mem_opendir(void *context, SilcSFTP sftp,
   /* Directory opened, return handle */
   handle = mem_create_handle(fs, 0, entry);
   if (handle)
-    (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle, 
+    (*callback)(sftp, SILC_SFTP_STATUS_OK, (SilcSFTPHandle)handle,
                callback_context);
   else
-    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL, 
+    (*callback)(sftp, SILC_SFTP_STATUS_PERMISSION_DENIED, NULL,
                callback_context);
 }
 
@@ -795,8 +795,13 @@ void mem_readdir(void *context, SilcSFTP sftp,
             ((entry->perm & SILC_SFTP_FS_PERM_WRITE) ? 'w' : '-'),
             ((entry->perm & SILC_SFTP_FS_PERM_EXEC) ? 'x' : '-'),
             (entry->directory ? (int)entry->entry_count : 1),
-            filesize, date, entry->name,
-            (entry->directory ? "/" : 
+#ifndef SILC_WIN32
+            (unsigned long long)filesize,
+#else
+            (unsigned long)filesize,
+#endif
+            date, entry->name,
+            (entry->directory ? "/" :
              ((entry->perm & SILC_SFTP_FS_PERM_EXEC) ? "*" : "")));
 
     /* Add attributes */
@@ -864,7 +869,7 @@ void mem_stat(void *context, SilcSFTP sftp,
   if (entry->directory || !entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Get real stat */
   ret = stat(entry->data + 7, &stats);
@@ -877,7 +882,7 @@ void mem_stat(void *context, SilcSFTP sftp,
   if (!attrs) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
   attrs->flags = (SILC_SFTP_ATTR_SIZE |
                  SILC_SFTP_ATTR_UIDGID |
                  SILC_SFTP_ATTR_ACMODTIME);
@@ -888,7 +893,7 @@ void mem_stat(void *context, SilcSFTP sftp,
   attrs->mtime = stats.st_mtime;
 
   /* Return attributes */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs,
              callback_context);
 
   silc_sftp_attr_free(attrs);
@@ -918,7 +923,7 @@ void mem_lstat(void *context, SilcSFTP sftp,
   if (entry->directory || !entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Get real stat */
 #ifndef SILC_WIN32
@@ -935,7 +940,7 @@ void mem_lstat(void *context, SilcSFTP sftp,
   if (!attrs) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
   attrs->flags = (SILC_SFTP_ATTR_SIZE |
                  SILC_SFTP_ATTR_UIDGID |
                  SILC_SFTP_ATTR_ACMODTIME);
@@ -946,7 +951,7 @@ void mem_lstat(void *context, SilcSFTP sftp,
   attrs->mtime = stats.st_mtime;
 
   /* Return attributes */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs,
              callback_context);
 
   silc_sftp_attr_free(attrs);
@@ -965,7 +970,7 @@ void mem_fstat(void *context, SilcSFTP sftp,
   if (h->entry->directory || !h->entry->data) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
 
   /* Get real stat */
   ret = fstat(h->fd, &stats);
@@ -978,7 +983,7 @@ void mem_fstat(void *context, SilcSFTP sftp,
   if (!attrs) {
     (*callback)(sftp, SILC_SFTP_STATUS_FAILURE, NULL, callback_context);
     return;
-  }    
+  }
   attrs->flags = (SILC_SFTP_ATTR_SIZE |
                  SILC_SFTP_ATTR_UIDGID |
                  SILC_SFTP_ATTR_ACMODTIME);
@@ -989,12 +994,12 @@ void mem_fstat(void *context, SilcSFTP sftp,
   attrs->mtime = stats.st_mtime;
 
   /* Return attributes */
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPAttributes)attrs,
              callback_context);
 
   silc_sftp_attr_free(attrs);
 }
-     
+
 void mem_setstat(void *context, SilcSFTP sftp,
                 const char *path,
                 SilcSFTPAttributes attrs,
@@ -1002,7 +1007,7 @@ void mem_setstat(void *context, SilcSFTP sftp,
                 void *callback_context)
 {
   /* Setstat is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
@@ -1013,7 +1018,7 @@ void mem_fsetstat(void *context, SilcSFTP sftp,
                  void *callback_context)
 {
   /* Fsetstat is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
@@ -1034,7 +1039,7 @@ void mem_symlink(void *context, SilcSFTP sftp,
                 void *callback_context)
 {
   /* Symlink is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, NULL,
              callback_context);
 }
 
@@ -1074,7 +1079,7 @@ void mem_realpath(void *context, SilcSFTP sftp,
     goto fail;
   name->count = 1;
 
-  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPName)name, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OK, (const SilcSFTPName)name,
              callback_context);
 
   silc_sftp_name_free(name);
@@ -1092,7 +1097,7 @@ void mem_extended(void *context, SilcSFTP sftp,
                  void *callback_context)
 {
   /* Extended is not supported */
-  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, 0, 
+  (*callback)(sftp, SILC_SFTP_STATUS_OP_UNSUPPORTED, NULL, 0,
              callback_context);
 }
 
index 8c96355aac2a08a9eda17852fd05264d13a6314b..cbfbe43c2ca63ca5ddeaef931c33de5cf75f2e07 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  sftp_server.c 
+  sftp_server.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@ typedef struct {
 /* General routine to send SFTP packet to the SFTP client. */
 
 static void silc_sftp_send_packet(SilcSFTPServer sftp,
-                                 SilcSFTPPacket type, 
+                                 SilcSFTPPacket type,
                                  SilcUInt32 len, ...)
 {
   SilcBuffer tmp;
@@ -50,7 +50,7 @@ static void silc_sftp_send_packet(SilcSFTPServer sftp,
     return;
   sftp->packet = tmp;
 
-  SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data, 
+  SILC_LOG_HEXDUMP(("SFTP packet to client"), sftp->packet->data,
                   sftp->packet->len);
 
   /* Send the packet */
@@ -86,12 +86,12 @@ static void silc_sftp_server_status(SilcSFTP sftp,
                                    void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   int mlen, llen;
 
   SILC_LOG_DEBUG(("Status callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
-  
+
   if (!message)
     message = "";
   if (!language_tag)
@@ -117,7 +117,7 @@ static void silc_sftp_server_handle(SilcSFTP sftp,
                                    void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   unsigned char *hdata;
   SilcUInt32 hdata_len;
 
@@ -152,7 +152,7 @@ static void silc_sftp_server_data(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
 
   SILC_LOG_DEBUG(("Data callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
@@ -177,7 +177,7 @@ static void silc_sftp_server_name(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   SilcBuffer namebuf;
 
   SILC_LOG_DEBUG(("Name callback"));
@@ -208,7 +208,7 @@ static void silc_sftp_server_attr(SilcSFTP sftp,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
   SilcBuffer attr_buf;
 
   SILC_LOG_DEBUG(("Attr callback"));
@@ -242,7 +242,7 @@ static void silc_sftp_server_extended(SilcSFTP sftp,
                                      void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
-  SilcUInt32 id = (SilcUInt32)context;
+  SilcUInt32 id = SILC_PTR_TO_32(context);
 
   SILC_LOG_DEBUG(("Extended callback"));
   SILC_LOG_DEBUG(("Request ID: %d", id));
@@ -300,7 +300,7 @@ void silc_sftp_server_shutdown(SilcSFTP sftp)
 
 void silc_sftp_server_set_monitor(SilcSFTP sftp,
                                  SilcSFTPMonitors monitors,
-                                 SilcSFTPMonitor monitor, 
+                                 SilcSFTPMonitor monitor,
                                  void *context)
 {
   SilcSFTPServer server = (SilcSFTPServer)sftp;
@@ -332,7 +332,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
   SILC_LOG_DEBUG(("Start"));
 
   /* Parse the packet */
-  type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload, 
+  type = silc_sftp_packet_decode(packet->buffer, (unsigned char **)&payload,
                                 &payload_len);
   if (!type)
     return;
@@ -380,7 +380,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
                                 SILC_STR_UI_INT(&id),
                                 SILC_STR_UI32_STRING_ALLOC(&filename),
                                 SILC_STR_UI_INT(&pflags),
-                                SILC_STR_UI32_NSTRING(&attr_buf, 
+                                SILC_STR_UI32_NSTRING(&attr_buf,
                                                       &attr_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -407,7 +407,8 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Open operation */
       server->fs->fs->sftp_open(server->fs->fs_context, sftp, filename, pflags,
-                               attrs, silc_sftp_server_handle, (void *)id);
+                               attrs, silc_sftp_server_handle,
+                               SILC_32_TO_PTR(id));
 
       silc_free(filename);
       silc_sftp_attr_free(attrs);
@@ -423,7 +424,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -446,7 +447,8 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Close operation */
       server->fs->fs->sftp_close(server->fs->fs_context, sftp, handle,
-                                silc_sftp_server_status, (void *)id);
+                                silc_sftp_server_status, SILC_32_TO_PTR(id));
+
     }
     break;
 
@@ -461,7 +463,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_UI_INT64(&offset),
                                 SILC_STR_UI_INT(&len),
@@ -478,6 +480,11 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
        break;
       }
 
+      /* Read operation */
+      server->fs->fs->sftp_read(server->fs->fs_context, sftp,
+                               handle, offset, len,
+                               silc_sftp_server_data, SILC_32_TO_PTR(id));
+
       /* Call monitor */
       if (server->monitors & SILC_SFTP_MONITOR_READ && server->monitor) {
        mdata.offset = offset;
@@ -485,11 +492,6 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
        (*server->monitor)(sftp, SILC_SFTP_MONITOR_READ, &mdata,
                           server->monitor_context);
       }
-
-      /* Read operation */
-      server->fs->fs->sftp_read(server->fs->fs_context, sftp, 
-                               handle, offset, len,
-                               silc_sftp_server_data, (void *)id);
     }
     break;
 
@@ -505,10 +507,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_UI_INT64(&offset),
-                                SILC_STR_UI32_NSTRING(&data, 
+                                SILC_STR_UI32_NSTRING(&data,
                                                       &data_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -523,6 +525,11 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
        break;
       }
 
+      /* Write operation */
+      server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset,
+                                (const unsigned char *)data, data_len,
+                                silc_sftp_server_status, SILC_32_TO_PTR(id));
+
       /* Call monitor */
       if (server->monitors & SILC_SFTP_MONITOR_WRITE && server->monitor) {
        mdata.offset = offset;
@@ -530,11 +537,6 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
        (*server->monitor)(sftp, SILC_SFTP_MONITOR_WRITE, &mdata,
                           server->monitor_context);
       }
-
-      /* Write operation */
-      server->fs->fs->sftp_write(server->fs->fs_context, sftp, handle, offset, 
-                                (const unsigned char *)data, data_len,
-                                silc_sftp_server_status, (void *)id);
     }
     break;
 
@@ -558,7 +560,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Remove operation */
       server->fs->fs->sftp_remove(server->fs->fs_context, sftp, filename,
-                                 silc_sftp_server_status, (void *)id);
+                                 silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_free(filename);
     }
@@ -587,9 +589,9 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       }
 
       /* Rename operation */
-      server->fs->fs->sftp_rename(server->fs->fs_context, sftp, 
+      server->fs->fs->sftp_rename(server->fs->fs_context, sftp,
                                  filename, newname,
-                                 silc_sftp_server_status, (void *)id);
+                                 silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_free(filename);
       silc_free(newname);
@@ -633,7 +635,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Mkdir operation */
       server->fs->fs->sftp_mkdir(server->fs->fs_context, sftp, path, attrs,
-                                silc_sftp_server_status, (void *)id);
+                                silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_sftp_attr_free(attrs);
       silc_free(path);
@@ -660,7 +662,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Rmdir operation */
       server->fs->fs->sftp_rmdir(server->fs->fs_context, sftp, path,
-                                silc_sftp_server_status, (void *)id);
+                                silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -686,7 +688,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Opendir operation */
       server->fs->fs->sftp_opendir(server->fs->fs_context, sftp, path,
-                                  silc_sftp_server_handle, (void *)id);
+                                  silc_sftp_server_handle, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -701,7 +703,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -724,7 +726,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Readdir operation */
       server->fs->fs->sftp_readdir(server->fs->fs_context, sftp, handle,
-                                  silc_sftp_server_name, (void *)id);
+                                  silc_sftp_server_name, SILC_32_TO_PTR(id));
     }
     break;
 
@@ -748,7 +750,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Stat operation */
       server->fs->fs->sftp_stat(server->fs->fs_context, sftp, path,
-                               silc_sftp_server_attr, (void *)id);
+                               silc_sftp_server_attr, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -774,7 +776,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Lstat operation */
       server->fs->fs->sftp_lstat(server->fs->fs_context, sftp, path,
-                                silc_sftp_server_attr, (void *)id);
+                                silc_sftp_server_attr, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -789,7 +791,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_END);
       if (ret < 0)
@@ -812,7 +814,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Fstat operation */
       server->fs->fs->sftp_fstat(server->fs->fs_context, sftp, handle,
-                                silc_sftp_server_attr, (void *)id);
+                                silc_sftp_server_attr, SILC_32_TO_PTR(id));
     }
     break;
 
@@ -853,7 +855,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Setstat operation */
       server->fs->fs->sftp_setstat(server->fs->fs_context, sftp, path, attrs,
-                                  silc_sftp_server_status, (void *)id);
+                                  silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_sftp_attr_free(attrs);
       silc_free(path);
@@ -870,7 +872,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       ret = silc_buffer_unformat(&buf,
                                 SILC_STR_UI_INT(&id),
-                                SILC_STR_UI32_NSTRING(&hdata, 
+                                SILC_STR_UI32_NSTRING(&hdata,
                                                       &hdata_len),
                                 SILC_STR_UI32_NSTRING(&attr_buf,
                                                       &attr_len),
@@ -905,9 +907,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       }
 
       /* Fsetstat operation */
-      server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp, 
+      server->fs->fs->sftp_fsetstat(server->fs->fs_context, sftp,
                                    handle, attrs,
-                                   silc_sftp_server_status, (void *)id);
+                                   silc_sftp_server_status,
+                                   SILC_32_TO_PTR(id));
 
       silc_sftp_attr_free(attrs);
     }
@@ -933,7 +936,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Readlink operation */
       server->fs->fs->sftp_readlink(server->fs->fs_context, sftp, path,
-                                   silc_sftp_server_name, (void *)id);
+                                   silc_sftp_server_name, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -963,7 +966,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Symlink operation */
       server->fs->fs->sftp_symlink(server->fs->fs_context, sftp, path, target,
-                                  silc_sftp_server_status, (void *)id);
+                                  silc_sftp_server_status, SILC_32_TO_PTR(id));
 
       silc_free(path);
       silc_free(target);
@@ -990,7 +993,7 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
 
       /* Realpath operation */
       server->fs->fs->sftp_realpath(server->fs->fs_context, sftp, path,
-                                   silc_sftp_server_name, (void *)id);
+                                   silc_sftp_server_name, SILC_32_TO_PTR(id));
 
       silc_free(path);
     }
@@ -1027,9 +1030,10 @@ void silc_sftp_server_receive_process(SilcSFTP sftp,
       }
 
       /* Extended operation */
-      server->fs->fs->sftp_extended(server->fs->fs_context, sftp, 
+      server->fs->fs->sftp_extended(server->fs->fs_context, sftp,
                                    request, data, data_len,
-                                   silc_sftp_server_extended, (void *)id);
+                                   silc_sftp_server_extended,
+                                   SILC_32_TO_PTR(id));
 
       silc_free(request);
     }
index b7017448e9a83ca537efb92f6009de672bab5c37..38b300b6277e4c807b68e8c7c284fadec5acd874 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcsftp.h 
+  silcsftp.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
  *
  * DESCRIPTION
  *
- *    SILC SFTP Interface is the implementation of the SSH File Transfer
+ *    SILC SFTP Interface is the implementation of the Secure File Transfer
  *    Protocol.  The interface defines the SFTP client and the SFTP server.
  *    The SFTP is the mandatory file transfer protocol in the SILC protocol.
  *    The SFTP server implementation is filesystem independent and generic
@@ -39,7 +39,7 @@
 /****s* silcsftp/SilcSFTPAPI/SilcSFTP
  *
  * NAME
- * 
+ *
  *    typedef struct SilcSFTPStruct *SilcSFTP;
  *
  * DESCRIPTION
@@ -47,7 +47,7 @@
  *    This context is the actual SFTP client and SFTP server, and is
  *    allocated by silc_sftp_client_start or silc_sftp_server_start and
  *    given as argument usually to all silc_sftp_* functions.  It is freed
- *    by the silc_sftp_client_shutdown or silc_sftp_server_shutdown 
+ *    by the silc_sftp_client_shutdown or silc_sftp_server_shutdown
  *    functions.
  *
  ***/
@@ -56,7 +56,7 @@ typedef struct SilcSFTPStruct *SilcSFTP;
 /****d* silcsftp/SilcSFTPAPI/SilcSFTPVersion
  *
  * NAME
- * 
+ *
  *    typedef SilcUInt32 SilcSFTPVersion;
  *
  * DESCRIPTION
@@ -74,7 +74,7 @@ typedef SilcUInt32 SilcSFTPVersion;
 /****d* silcsftp/SilcSFTPAPI/SilcSFTPStatus
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcSFTPStatus
  *
  * DESCRIPTION
@@ -95,13 +95,33 @@ typedef enum {
   SILC_SFTP_STATUS_NO_CONNECTION       = 6,  /* No connection to server */
   SILC_SFTP_STATUS_CONNECTION_LOST     = 7,  /* Connection lost to server */
   SILC_SFTP_STATUS_OP_UNSUPPORTED      = 8,  /* Operation unsupported */
+  SILC_SFTP_STATUS_INVALID_HANDLE      = 9,  /* Invalid file handle */
+  SILC_SFTP_STATUS_NO_SUCH_PATH        = 10, /* Path does not exist */
+  SILC_SFTP_STATUS_FILE_ALREADY_EXIST  = 11, /* File already exists */
+  SILC_SFTP_STATUS_WRITE_PROTECT       = 12, /* Read-only or protected */
+  SILC_SFTP_STATUS_NO_MEDIA            = 13, /* No media available */
+  SILC_SFTP_STATUS_NO_SPACE_ON_DEVICE  = 14, /* No space on device */
+  SILC_SFTP_STATUS_QUOTA_EXCEEDED      = 15, /* Quota limit reached */
+  SILC_SFTP_STATUS_UNKNOWN_PRINCIBLE   = 16, /* Unknown princible */
+  SILC_SFTP_STATUS_LOCK_CONFLICT       = 17, /* File already locked */
+  SILC_SFTP_STATUS_NOT_EMPTY           = 18, /* Directory not empty */
+  SILC_SFTP_STATUS_NOT_A_DIRECTORY     = 19, /* Not a directory */
+  SILC_SFTP_STATUS_INVALID_FILENAME    = 20, /* Invalid filename */
+  SILC_SFTP_STATUS_LINK_LOOP           = 21, /* Too many symlinks */
+  SILC_SFTP_STATUS_CANNOT_DELETE       = 22, /* Could not delete file */
+  SILC_SFTP_STATUS_INVALID_PARAMETER   = 23, /* Invalid parameter */
+  SILC_SFTP_STATUS_FILE_IS_A_DIRECTORY = 24, /* File is a directory file */
+  SILC_SFTP_STATUS_BR_LOCK_CONFLICT    = 25, /* Byte range lock conflict */
+  SILC_SFTP_STATUS_BR_LOCK_REFUSED     = 26, /* Byte range lock refused */
+  SILC_SFTP_STATUS_DELETE_PENDING      = 27, /* File is being deleted */
+  SILC_SFTP_STATUS_FILE_CORRUPT        = 28, /* File is corrupted */
 } SilcSFTPStatus;
 /***/
 
 /****d* silcsftp/SilcSFTPAPI/SilcSFTPFileOperation
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcSFTPFileOperation
  *
  * DESCRIPTION
@@ -125,13 +145,13 @@ typedef enum {
 /****s* silcsftp/SilcSFTPAPI/SilcSFTPAttributes
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } *SilcSFTPAttributes, SilcSFTPAttributesStruct;
  *
  * DESCRIPTION
  *
  *    SFTP File attributes structure represents the attributes for a file.
- *    This structure can be used by the client to send attributes to the 
+ *    This structure can be used by the client to send attributes to the
  *    server, and by server to return file attributes to the client.
  *
  ***/
@@ -152,7 +172,7 @@ typedef struct {
 /****s* silcsftp/SilcSFTPAPI/SilcSFTPName
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } *SilcSFTPName, SilcSFTPNameStruct
  *
  * DESCRIPTION
@@ -173,7 +193,7 @@ typedef struct {
 /****s* silcsftp/SilcSFTPAPI/SilcSFTPHandle
  *
  * NAME
- * 
+ *
  *    typedef struct SilcSFTPHandleStruct *SilcSFTPHandle;
  *
  * DESCRIPTION
@@ -189,7 +209,7 @@ typedef struct SilcSFTPHandleStruct *SilcSFTPHandle;
  *
  * SYNOPSIS
  *
- *    typedef void (*SilcSFTPSendPacketCallback)(SilcBuffer packet, 
+ *    typedef void (*SilcSFTPSendPacketCallback)(SilcBuffer packet,
  *                                               void *context);
  *
  * DESCRIPTION
@@ -412,7 +432,7 @@ void silc_sftp_client_receive_process(SilcSFTP sftp,
  *
  * SYNOPSIS
  *
- *    void silc_sftp_open(SilcSFTP sftp, 
+ *    void silc_sftp_open(SilcSFTP sftp,
  *                        const char *filename,
  *                        SilcSFTPFileOperation pflags,
  *                        SilcSFTPAttributes attrs,
@@ -426,7 +446,7 @@ void silc_sftp_client_receive_process(SilcSFTP sftp,
  *    `callback' to return the opened file handle.
  *
  ***/
-void silc_sftp_open(SilcSFTP sftp, 
+void silc_sftp_open(SilcSFTP sftp,
                    const char *filename,
                    SilcSFTPFileOperation pflags,
                    SilcSFTPAttributes attrs,
@@ -459,7 +479,7 @@ void silc_sftp_close(SilcSFTP sftp,
  *
  *    void silc_sftp_read(SilcSFTP sftp,
  *                        SilcSFTPHandle handle,
- *                        SilcUInt64 offset, 
+ *                        SilcUInt64 offset,
  *                        SilcUInt32 len,
  *                        SilcSFTPDataCallback callback,
  *                        void *context);
@@ -473,7 +493,7 @@ void silc_sftp_close(SilcSFTP sftp,
  ***/
 void silc_sftp_read(SilcSFTP sftp,
                    SilcSFTPHandle handle,
-                   SilcUInt64 offset, 
+                   SilcUInt64 offset,
                    SilcUInt32 len,
                    SilcSFTPDataCallback callback,
                    void *context);
@@ -493,7 +513,7 @@ void silc_sftp_read(SilcSFTP sftp,
  * DESCRIPTION
  *
  *    Writes to a file indicated by the file handle `handle' starting from
- *    offset of `offset' at most `data_len' bytes of `data'.  The `callback' 
+ *    offset of `offset' at most `data_len' bytes of `data'.  The `callback'
  *    is called to indicate the status of the writing.
  *
  ***/
@@ -814,7 +834,7 @@ void silc_sftp_realpath(SilcSFTP sftp,
  *
  * DESCRIPTION
  *
- *    Performs an extended operation indicated by the `request' with 
+ *    Performs an extended operation indicated by the `request' with
  *    optional extended operation data indicated by the `data'.  The callback
  *    is called to return any data associated with the extended request.
  *
@@ -836,7 +856,7 @@ void silc_sftp_extended(SilcSFTP sftp,
  * SYNOPSIS
  *
  *    SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet,
- *                                    void *send_context, 
+ *                                    void *send_context,
  *                                    SilcSFTPFilesystem fs);
  *
  * DESCRIPTION
@@ -849,7 +869,7 @@ void silc_sftp_extended(SilcSFTP sftp,
  *
  ***/
 SilcSFTP silc_sftp_server_start(SilcSFTPSendPacketCallback send_packet,
-                               void *send_context, 
+                               void *send_context,
                                SilcSFTPFilesystem fs);
 
 /****f* silcsftp/SilcSFTPAPI/silc_sftp_server_shutdown
@@ -870,7 +890,7 @@ void silc_sftp_server_shutdown(SilcSFTP sftp);
 /****d* silcsftp/SilcSFTPAPI/SilcSFTPMonitors
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcSFTPMonitors;
  *
  * DESCRIPTION
@@ -907,7 +927,7 @@ typedef enum {
 /****s* silcsftp/SilcSFTPAPI/SilcSFTPMonitorData
  *
  * NAME
- * 
+ *
  *    typedef struct { ... } *SilcSFTPMonitorData, SilcSFTPMonitorDataStruct;
  *
  * DESCRIPTION
@@ -958,7 +978,7 @@ typedef void (*SilcSFTPMonitor)(SilcSFTP sftp,
  *
  *    void silc_sftp_server_set_monitor(SilcSFTP sftp,
  *                                      SilcSFTPMonitors monitors,
- *                                      SilcSFTPMonitor monitor, 
+ *                                      SilcSFTPMonitor monitor,
  *                                      void *context);
  *
  * DESCRIPTION
@@ -970,7 +990,7 @@ typedef void (*SilcSFTPMonitor)(SilcSFTP sftp,
  ***/
 void silc_sftp_server_set_monitor(SilcSFTP sftp,
                                  SilcSFTPMonitors monitors,
-                                 SilcSFTPMonitor monitor, 
+                                 SilcSFTPMonitor monitor,
                                  void *context);
 
 /* Function that is called to process the incmoing SFTP packet. */
similarity index 86%
rename from lib/silcsim/Makefile.am
rename to lib/silcsim/Makefile.ad
index 3e45d3d7521ff8b513100b8bd6570ad39613957b..baf8d782081c728dbb2d8666417dcf5b48098996 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -35,7 +34,6 @@ SIM_CIPHER_OBJS = \
         none.o \
         blowfish.o \
         rc5.o \
-        rc6.o \
         aes.o \
         rsa.o \
         twofish.o \
@@ -76,9 +74,9 @@ $(SIM_HASH_OBJS):
 
 CLEANFILES = *.sim.so *.la
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS = silcsim.h silcsimutil.h
-endif
+#endif SILC_DIST_TOOLKIT
 
 EXTRA_DIST = *.h
 
similarity index 74%
rename from lib/silcske/Makefile.am
rename to lib/silcske/Makefile.ad
index 0d18470a5cab807f87bc44fb45dee0dc64923e3c..b6cad66559bf0606066546822672eeb95efb2901 100644 (file)
@@ -1,14 +1,13 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -25,13 +24,13 @@ libsilcske_la_SOURCES = \
        payload.c \
         groups.c
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS =              \
        silcske_groups.h        \
        silcske_payload.h       \
        silcske_status.h        \
        silcske.h
-endif
+#endif SILC_DIST_TOOLKIT
 
 EXTRA_DIST = *.h
 
index 6e178a56b54c65c55484e2f75b6aef68a9bfbf96..46c522ac0a64c7d2d5ae7e7f4a0b62d71ef48386 100644 (file)
@@ -16,6 +16,8 @@
 @LINK=silcconfig.html:SILC Config Interface
 @LINK=silcfileutil.html:SILC File Util Interface
 @LINK=silcstrutil.html:SILC String Util Interface
+@LINK=silcutf8.html:SILC UTF-8 Interface
+@LINK=silcstringprep.html:SILC Stringprep Interface
 @LINK=silcutil.html:SILC Util Interface
 @LINK=silclist.html:SILC List Interface
 @LINK=silcdlist.html:SILC Dynamic List Interface
similarity index 81%
rename from lib/silcutil/Makefile.am
rename to lib/silcutil/Makefile.ad
index b5530d6ef12ab0253af28a9fc04c188475c65525..c9ba5f61ffb1a1a2abb83ba1fda97779d27bf487 100644 (file)
@@ -1,9 +1,9 @@
 #
-#  Makefile.am
+#  Makefile.ad
 #
 #  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 - 2002 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
@@ -35,13 +35,12 @@ endif
 endif
 endif
 
-if SILC_DIST_TOOLKIT
+DIST_SUBDIRS=win32 epoc beos os2 unix
+
+#ifdef SILC_DIST_TOOLKIT
 SILC_DIST_SOURCE = stacktrace.c
 SILC_DIST_HEADER = stacktrace.h
-else
-SILC_DIST_SOURCE =
-SILC_DIST_HEADER =
-endif
+#endif SILC_DIST_TOOLKIT
 
 noinst_LTLIBRARIES = libsilcutil.la
 
@@ -60,9 +59,11 @@ libsilcutil_la_SOURCES = \
        silcsockconn.c  \
        silcprotocol.c  \
        silcvcard.c     \
-       silcapputil.c
+       silcapputil.c   \
+       silcutf8.c      \
+       silcstringprep.c
 
-if SILC_DIST_TOOLKIT
+#ifdef SILC_DIST_TOOLKIT
 include_HEADERS =      \
        $(SILC_DIST_HEADER) \
        silcbuffer.h    \
@@ -84,9 +85,13 @@ include_HEADERS =    \
        silcstrutil.h   \
        silcvcard.h     \
        silcapputil.h   \
+       silcutf8.h      \
+       silcstringprep.h        \
        silctypes.h
-endif
 
-EXTRA_DIST = *.h
+SILC_EXTRA_DIST = tests
+#endif SILC_DIST_TOOLKIT
+
+EXTRA_DIST = *.h $(SILC_EXTRA_DIST)
 
 include $(top_srcdir)/Makefile.defines.in
index 1f486afad170656c23a30f0b0a18d9450654a4a6..a79ee597549e91a21c7ae838b3cb6335a64e8202 100644 (file)
@@ -175,21 +175,24 @@ New pair of keys will be created.  Please, answer to following questions.\n\
   }
 
   if (!pass) {
-    char *pass2 = NULL;
-    pass = silc_get_input("Private key passphrase: ", TRUE);
-    if (!pass) {
-      pass = strdup("");
-    } else {
-      while (TRUE) {
+    while (TRUE) {
+      char *pass2 = NULL;
+      pass = silc_get_input("Private key passphrase: ", TRUE);
+      if (!pass) {
+        pass = strdup("");
+       break;
+      } else {
+       bool match;
        printf("\n");
        pass2 = silc_get_input("Retype private key passphrase: ", TRUE);
        if (!pass2)
          pass2 = strdup("");
-       if (!strcmp(pass, pass2))
+       match = !strcmp(pass, pass2);
+       silc_free(pass2);
+       if (match)
          break;
-       fprintf(stderr, "\nPassphrases do not match");
+       fprintf(stderr, "\nPassphrases do not match\n\n");
       }
-      silc_free(pass2);
     }
   }
 
index a189c2903a7e145fb6ccc88ee9fbd31e4b4d298a..65dd76b42c6ac102e7988b72851f6eecafbb8430 100644 (file)
@@ -524,7 +524,7 @@ int silc_buffer_strformat(SilcBuffer dst, ...)
 
   /* Parse the arguments by formatting type. */
   while(1) {
-    char *string = va_arg(va, char *);
+    char *string = (char *)va_arg(va, void *);
 
     if (!string)
       continue;
index 86c155e3a7bb65cd143cfacafa3398b4db365c22..3ffc74991f7972a501b65809ab8a1a8c51272219 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcbuffmt.h 
+  silcbuffmt.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -122,14 +122,14 @@ int silc_buffer_unformat_vp(SilcBuffer src, va_list ap);
  *
  *   Formats a buffer from variable argument list of strings.  Each
  *   string must be NULL-terminated and the variable argument list must
- *   be end with SILC_STR_END argument.  This allows that a string in
+ *   be end with SILC_STRFMT_END argument.  This allows that a string in
  *   the list can be NULL, in which case it is skipped.  This automatically
  *   allocates the space for the buffer data but `dst' must be already
  *   allocated by the caller.
  *
  * EXAMPLE
  *
- *    ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STR_END);
+ *    ret = silc_buffer_strformat(buffer, "foo", "bar", SILC_STRFMT_END);
  *    if (ret < 0)
  *      error;
  *
@@ -292,7 +292,7 @@ typedef enum {
  *    automatically.
  *
  *    Example:
- * 
+ *
  *    Formatting:    ..., SILC_STR_UI_INT(strlen(string)),
  *                        SILC_STR_UI32_STRING(string), ...
  *    Unformatting:  ..., SILC_STR_UI32_STRING(&string), ...
@@ -412,4 +412,18 @@ typedef enum {
  ***/
 #define SILC_STR_END SILC_BUFFER_PARAM_END
 
+/****d* silcutil/SilcBufferFormatAPI/SILC_STRFMT_END
+ *
+ * NAME
+ *
+ *    #define SILC_STRFMT_END ...
+ *
+ * DESCRIPTION
+ *
+ *    Marks end of the argument list in silc_buffer_strformat function.
+ *    This must be at the end of the argument list or error will occur.
+ *
+ ***/
+#define SILC_STRFMT_END (void *)SILC_STR_END
+
 #endif /* !SILCBUFFMT_H */
index 52112ee3903bac053bcdffd982b34faa6e2ff128..23d2c17c12901a0e1c9b56886bc3bdc172ba88d4 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -101,7 +101,7 @@ int silc_file_writefile_mode(const char *filename, const char *buffer,
   flags |= O_BINARY;
 #endif /* O_BINARY */
 
-  if ((fd = open(filename, flags, 0644)) == -1) {
+  if ((fd = open(filename, flags, mode)) == -1) {
     SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
                    strerror(errno)));
     return -1;
index 6478382a94e51e19eadfe4d6ae261aafa1cceca9..ab5a25a51f1cf28e057eedcf47e2f019fb62bceb 100644 (file)
@@ -38,7 +38,7 @@
 #endif
 
 /* Default size of the hash table (index to prime table) */
-#define SILC_HASH_TABLE_SIZE 3
+#define SILC_HASH_TABLE_SIZE 2
 
 /* Produce the index by hashing the key */
 #define SILC_HASH_TABLE_HASH(f, c) \
@@ -79,7 +79,7 @@ struct SilcHashTableStruct {
    be one of these. */
 const SilcUInt32 primesize[42] =
 {
-  1, 3, 5, 11, 17, 37, 67, 109, 131, 163, 257, 367, 521, 823, 1031,
+  3, 5, 11, 17, 37, 67, 109, 131, 163, 257, 367, 521, 823, 1031,
   1237, 2053, 2777, 4099, 6247, 8209, 14057, 16411, 21089, 32771, 47431,
   65537, 106721, 131101, 262147, 360163, 524309, 810343, 1048583, 2097169,
   4194319, 6153409, 8388617, 13845163, 16777259, 33554467, 67108879
@@ -653,21 +653,8 @@ bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
 bool silc_hash_table_find(SilcHashTable ht, void *key,
                          void **ret_key, void **ret_context)
 {
-  SilcHashTableEntry *entry;
-
-  entry = silc_hash_table_find_internal_simple(ht, key, ht->hash,
-                                              ht->hash_user_context,
-                                              ht->compare,
-                                              ht->compare_user_context);
-  if (*entry == NULL)
-    return FALSE;
-
-  if (ret_key)
-    *ret_key = (*entry)->key;
-  if (ret_context)
-    *ret_context = (*entry)->context;
-
-  return TRUE;
+  return silc_hash_table_find_ext(ht, key, ret_key, ret_context,
+                                 NULL, NULL, NULL, NULL);
 }
 
 /* Same as above but with specified hash and comparison functions. */
@@ -706,13 +693,31 @@ bool silc_hash_table_find_ext(SilcHashTable ht, void *key,
 
 bool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
                                     void *context, void **ret_key)
+{
+  return silc_hash_table_find_by_context_ext(ht, key, context, ret_key,
+                                            NULL, NULL, NULL, NULL);
+}
+
+/* Same as above but with specified hash and comparison functions. */
+
+bool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
+                                        void *context, void **ret_key,
+                                        SilcHashFunction hash,
+                                        void *hash_user_context,
+                                        SilcHashCompare compare,
+                                        void *compare_user_context)
 {
   SilcHashTableEntry *entry;
 
   entry = silc_hash_table_find_internal_context(ht, key, context, NULL,
-                                               ht->hash,
+                                               hash ? hash : ht->hash,
+                                               hash_user_context ?
+                                               hash_user_context :
                                                ht->hash_user_context,
+                                               compare ? compare :
                                                ht->compare,
+                                               compare_user_context ?
+                                               compare_user_context :
                                                ht->compare_user_context);
   if (!entry || !(*entry))
     return FALSE;
index 478ea184a6a23128f8d710c899bb26a4de2a151b..612038034c9f4c38414c0e8e2f9e75cd4f87d860 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silchashtable.h 
+  silchashtable.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2002 Pekka Riikonen
+  Copyright (C) 2001 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@
 /****s* silcutil/SilcHashTableAPI/SilcHashTable
  *
  * NAME
- * 
+ *
  *    typedef struct SilcHashTableStruct *SilcHashTable;
  *
  * DESCRIPTION
@@ -63,13 +63,13 @@ typedef struct SilcHashTableStruct *SilcHashTable;
 /****s* silcutil/SilcHashTableAPI/SilcHashTableList
  *
  * NAME
- * 
+ *
  *    typedef struct SilcHashTableListStruct SilcHashTableList;
  *
  * DESCRIPTION
  *
  *    This structure is used to tarverse the hash table. This structure
- *    is given as argument to the silc_hash_table_list function to 
+ *    is given as argument to the silc_hash_table_list function to
  *    initialize it and then used to traverse the hash table with the
  *    silc_hash_table_get function. It needs not be allocated or freed.
  *
@@ -114,7 +114,7 @@ typedef SilcUInt32 (*SilcHashFunction)(void *key, void *user_context);
  *
  * SYNOPSIS
  *
- *    typedef bool (*SilcHashCompare)(void *key1, void *key2, 
+ *    typedef bool (*SilcHashCompare)(void *key1, void *key2,
  *                                    void *user_context);
  *
  * DESCRIPTION
@@ -132,25 +132,25 @@ typedef bool (*SilcHashCompare)(void *key1, void *key2, void *user_context);
  *
  * SYNOPSIS
  *
- *    typedef void (*SilcHashDestructor)(void *key, void *context, 
+ *    typedef void (*SilcHashDestructor)(void *key, void *context,
  *                                       void *user_context);
  *
  * DESCRIPTION
  *
- *    A destructor callback that the library will call to destroy the 
+ *    A destructor callback that the library will call to destroy the
  *    `key' and `context'.  The application provides the function when
  *    allocating a new hash table. The `user_context' is application
  *    specific context and is delivered to the callback.
  *
  ***/
-typedef void (*SilcHashDestructor)(void *key, void *context, 
+typedef void (*SilcHashDestructor)(void *key, void *context,
                                   void *user_context);
 
 /****f* silcutil/SilcHashTableAPI/SilcHashForeach
  *
  * SYNOPSIS
  *
- *    typedef void (*SilcHashForeach)(void *key, void *context, 
+ *    typedef void (*SilcHashForeach)(void *key, void *context,
  *                                    void *user_context);
  *
  * DESCRIPTION
@@ -168,7 +168,7 @@ typedef void (*SilcHashForeach)(void *key, void *context, void *user_context);
  *
  * SYNOPSIS
  *
- *    SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, 
+ *    SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size,
  *                                        SilcHashFunction hash,
  *                                        void *hash_user_context,
  *                                        SilcHashCompare compare,
@@ -188,7 +188,7 @@ typedef void (*SilcHashForeach)(void *key, void *context, void *user_context);
  *    are optional.
  *
  ***/
-SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size, 
+SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size,
                                    SilcHashFunction hash,
                                    void *hash_user_context,
                                    SilcHashCompare compare,
@@ -291,7 +291,7 @@ bool silc_hash_table_del(SilcHashTable ht, void *key);
  *
  * SYNOPSIS
  *
- *    bool silc_hash_table_del_by_context(SilcHashTable ht, void *key, 
+ *    bool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
  *                                        void *context);
  *
  * DESCRIPTION
@@ -302,7 +302,7 @@ bool silc_hash_table_del(SilcHashTable ht, void *key);
  *    be used to check whether the correct entry is being deleted.
  *
  ***/
-bool silc_hash_table_del_by_context(SilcHashTable ht, void *key, 
+bool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
                                    void *context);
 
 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find
@@ -315,7 +315,7 @@ bool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
  * DESCRIPTION
  *
  *    Finds the entry in the hash table by the provided `key' as fast as
- *    possible. Return TRUE if the entry was found and FALSE otherwise. 
+ *    possible. Return TRUE if the entry was found and FALSE otherwise.
  *    The found entry is returned to the `ret_key' and `ret_context',
  *    respectively. If the `ret_key and `ret_context' are NULL then this
  *    maybe used only to check whether given key exists in the table.
@@ -350,7 +350,7 @@ bool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
  * SYNOPSIS
  *
  *    void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
- *                                      SilcHashForeach foreach, 
+ *                                      SilcHashForeach foreach,
  *                                      void *user_context);
  *
  * DESCRIPTION
@@ -450,7 +450,7 @@ void silc_hash_table_list_reset(SilcHashTableList *htl);
  *
  * SYNOPSIS
  *
- *    bool silc_hash_table_get(SilcHashTableList *htl, void **key, 
+ *    bool silc_hash_table_get(SilcHashTableList *htl, void **key,
  *                             void **context);
  *
  * DESCRIPTION
@@ -471,7 +471,7 @@ bool silc_hash_table_get(SilcHashTableList *htl, void **key, void **context);
  * SYNOPSIS
  *
  *    void silc_hash_table_add_ext(SilcHashTable ht, void *key, void *context,
- *                                 SilcHashFunction hash, 
+ *                                 SilcHashFunction hash,
  *                                 void *hash_user_context);
  *
  * DESCRIPTION
@@ -492,9 +492,9 @@ void silc_hash_table_add_ext(SilcHashTable ht, void *key, void *context,
  *
  * SYNOPSIS
  *
- *    void silc_hash_table_replace_ext(SilcHashTable ht, void *key, 
+ *    void silc_hash_table_replace_ext(SilcHashTable ht, void *key,
  *                                     void *context,
- *                                     SilcHashFunction hash, 
+ *                                     SilcHashFunction hash,
  *                                     void *hash_user_context);
  *
  * DESCRIPTION
@@ -509,7 +509,7 @@ void silc_hash_table_add_ext(SilcHashTable ht, void *key, void *context,
  *
  ***/
 void silc_hash_table_replace_ext(SilcHashTable ht, void *key, void *context,
-                                SilcHashFunction hash, 
+                                SilcHashFunction hash,
                                 void *hash_user_context);
 
 /****f* silcutil/SilcHashTableAPI/silc_hash_table_del_ext
@@ -517,9 +517,9 @@ void silc_hash_table_replace_ext(SilcHashTable ht, void *key, void *context,
  * SYNOPSIS
  *
  *    bool silc_hash_table_del_ext(SilcHashTable ht, void *key,
- *                                 SilcHashFunction hash, 
+ *                                 SilcHashFunction hash,
  *                                 void *hash_user_context,
- *                                 SilcHashCompare compare, 
+ *                                 SilcHashCompare compare,
  *                                 void *compare_user_context,
  *                                 SilcHashDestructor destructor,
  *                                 void *destructor_user_context);
@@ -539,9 +539,9 @@ void silc_hash_table_replace_ext(SilcHashTable ht, void *key, void *context,
  *
  ***/
 bool silc_hash_table_del_ext(SilcHashTable ht, void *key,
-                            SilcHashFunction hash, 
+                            SilcHashFunction hash,
                             void *hash_user_context,
-                            SilcHashCompare compare, 
+                            SilcHashCompare compare,
                             void *compare_user_context,
                             SilcHashDestructor destructor,
                             void *destructor_user_context);
@@ -550,11 +550,11 @@ bool silc_hash_table_del_ext(SilcHashTable ht, void *key,
  *
  * SYNOPSIS
  *
- *    bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key, 
+ *    bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
  *                                            void *context,
- *                                            SilcHashFunction hash, 
+ *                                            SilcHashFunction hash,
  *                                            void *hash_user_context,
- *                                            SilcHashCompare compare, 
+ *                                            SilcHashCompare compare,
  *                                            void *compare_user_context,
  *                                            SilcHashDestructor destructor,
  *                                            void *destructor_user_context);
@@ -574,11 +574,11 @@ bool silc_hash_table_del_ext(SilcHashTable ht, void *key,
  *    specific destructor function.
  *
  ***/
-bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key, 
+bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
                                        void *context,
-                                       SilcHashFunction hash, 
+                                       SilcHashFunction hash,
                                        void *hash_user_context,
-                                       SilcHashCompare compare, 
+                                       SilcHashCompare compare,
                                        void *compare_user_context,
                                        SilcHashDestructor destructor,
                                        void *destructor_user_context);
@@ -589,15 +589,15 @@ bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
  *
  *    bool silc_hash_table_find_ext(SilcHashTable ht, void *key,
  *                                  void **ret_key, void **ret_context,
- *                                  SilcHashFunction hash, 
+ *                                  SilcHashFunction hash,
  *                                  void *hash_user_context,
- *                                  SilcHashCompare compare, 
+ *                                  SilcHashCompare compare,
  *                                  void *compare_user_context);
  *
  * DESCRIPTION
  *
  *    Finds the entry in the hash table by the provided `key' as fast as
- *    possible. Return TRUE if the entry was found and FALSE otherwise. 
+ *    possible. Return TRUE if the entry was found and FALSE otherwise.
  *    The found entry is returned to the `ret_key' and `ret_context',
  *    respectively. If the `ret_key and `ret_context' are NULL then this
  *    maybe used only to check whether given key exists in the table.
@@ -610,21 +610,55 @@ bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
  ***/
 bool silc_hash_table_find_ext(SilcHashTable ht, void *key,
                              void **ret_key, void **ret_context,
-                             SilcHashFunction hash, 
+                             SilcHashFunction hash,
                              void *hash_user_context,
-                             SilcHashCompare compare, 
+                             SilcHashCompare compare,
                              void *compare_user_context);
 
+/****f* silcutil/SilcHashTableAPI/silc_hash_table_find_by_context_ext
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
+ *                                             void *context, void **ret_key,
+ *                                             SilcHashFunction hash,
+ *                                             void *hash_user_context,
+ *                                             SilcHashCompare compare,
+ *                                             void *compare_user_context);
+ *
+ * DESCRIPTION
+ *
+ *    Finds the entry in the hash table by the provided `key' and
+ *    `context' as fast as possible.  This is handy function when there
+ *    can be multiple same keys in the hash table.  By using this function
+ *    the specific key with specific context can be found.  Return
+ *    TRUE if the entry with the key and context was found and FALSE
+ *    otherwise.  The function returns only the key to `ret_key' since
+ *    the caller already knows the context.
+ *
+ *    The `hash' and `hash_user_context' are application specified hash
+ *    function. If not provided the hash table's default is used.
+ *    The `compare' and `compare_user_context' are application specified
+ *    comparing function. If not provided the hash table's default is used.
+ *
+ ***/
+bool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
+                                        void *context, void **ret_key,
+                                        SilcHashFunction hash,
+                                        void *hash_user_context,
+                                        SilcHashCompare compare,
+                                        void *compare_user_context);
+
 /****f* silcutil/SilcHashTableAPI/silc_hash_table_find_foreach_ext
  *
  * SYNOPSIS
  *
  *    void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
- *                                          SilcHashFunction hash, 
+ *                                          SilcHashFunction hash,
  *                                          void *hash_user_context,
- *                                          SilcHashCompare compare, 
+ *                                          SilcHashCompare compare,
  *                                          void *compare_user_context,
- *                                          SilcHashForeach foreach, 
+ *                                          SilcHashForeach foreach,
  *                                          void *foreach_user_context);
  *
  * DESCRIPTION
@@ -649,11 +683,11 @@ bool silc_hash_table_find_ext(SilcHashTable ht, void *key,
  *
  ***/
 void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
-                                     SilcHashFunction hash, 
+                                     SilcHashFunction hash,
                                      void *hash_user_context,
-                                     SilcHashCompare compare, 
+                                     SilcHashCompare compare,
                                      void *compare_user_context,
-                                     SilcHashForeach foreach, 
+                                     SilcHashForeach foreach,
                                      void *foreach_user_context);
 
 /****f* silcutil/SilcHashTableAPI/silc_hash_table_rehash_ext
@@ -661,7 +695,7 @@ void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
  * SYNOPSIS
  *
  *    void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
- *                                    SilcHashFunction hash, 
+ *                                    SilcHashFunction hash,
  *                                    void *hash_user_context);
  *
  * DESCRIPTION
@@ -676,7 +710,7 @@ void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
  *
  ***/
 void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
-                               SilcHashFunction hash, 
+                               SilcHashFunction hash,
                                void *hash_user_context);
 
 #endif
index 60e1bcc4f31e3ef32b44564ad5ebca45a77a62b8..2bf94112cf9bbb420177dc15ae19da22c43a1634 100644 (file)
@@ -131,7 +131,7 @@ do {                                                        \
  *    };
  *
  *    SilcList list;
- *    silc_list_init(list, struct SilcInternalEntryStruct, next, prev);
+ *    silc_list_init_prev(list, struct SilcInternalEntryStruct, next, prev);
  *
  ***/
 #define silc_list_init_prev(list, type, nextfield, prevfield)  \
index 736edb03f4daa8b671ef8a6183797dfec908b93d..976005266bb108c190096d9bd6134b79c103d838 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -123,7 +123,7 @@ static void silc_log_checksize(SilcLog log)
   /* It's too big */
   fprintf(log->fp, "[%s] [%s] Cycling log file, over max "
          "logsize (%lu kilobytes)\n",
-         silc_get_time(0), log->typename, log->maxsize / 1024);
+         silc_get_time(0), log->typename, (unsigned long)log->maxsize / 1024);
   fflush(log->fp);
   fclose(log->fp);
   memset(newname, 0, sizeof(newname));
@@ -137,6 +137,9 @@ static void silc_log_checksize(SilcLog log)
   if (!(log->fp = fopen(log->filename, "w")))
     SILC_LOG_WARNING(("Couldn't reopen logfile %s for type \"%s\": %s",
                      log->filename, log->typename, strerror(errno)));
+#ifdef HAVE_CHMOD
+  chmod(log->filename, 0600);
+#endif /* HAVE_CHMOD */
 }
 
 /* Reset a logging channel (close and reopen) */
@@ -279,6 +282,9 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
              filename, strerror(errno));
       return FALSE;
     }
+#ifdef HAVE_CHMOD
+    chmod(filename, 0600);
+#endif /* HAVE_CHMOD */
   }
 
   /* clean the logging channel */
@@ -302,7 +308,7 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
     if (silc_log_scheduled)
       return TRUE;
 
-    /* Add schedule hook with a short delay to make sure we'll use 
+    /* Add schedule hook with a short delay to make sure we'll use
        right delay */
     silc_schedule_task_add(scheduler, 0, silc_log_fflush_callback,
                           (void *) scheduler, 10, 0,
@@ -361,7 +367,7 @@ void silc_log_reset_all() {
 
 /* Outputs the debug message to stderr. */
 
-void silc_log_output_debug(char *file, char *function,
+void silc_log_output_debug(char *file, const char *function,
                           int line, char *string)
 {
   if (!silc_debug)
@@ -373,7 +379,7 @@ void silc_log_output_debug(char *file, char *function,
     goto end;
 
   if (silc_log_debug_cb) {
-    if ((*silc_log_debug_cb)(file, function, line, string,
+    if ((*silc_log_debug_cb)(file, (char *)function, line, string,
                             silc_log_debug_context))
       goto end;
   }
@@ -387,7 +393,7 @@ void silc_log_output_debug(char *file, char *function,
 
 /* Hexdumps a message */
 
-void silc_log_output_hexdump(char *file, char *function,
+void silc_log_output_hexdump(char *file, const char *function,
                             int line, void *data_in,
                             SilcUInt32 len, char *string)
 {
@@ -404,7 +410,8 @@ void silc_log_output_hexdump(char *file, char *function,
     goto end;
 
   if (silc_log_hexdump_cb) {
-    if ((*silc_log_hexdump_cb)(file, function, line, data_in, len, string,
+    if ((*silc_log_hexdump_cb)(file, (char *)function, line,
+                              data_in, len, string,
                               silc_log_hexdump_context))
       goto end;
   }
index eeaee1edf9283fab06005477da91c21f625835a3..624120356e8dbd9a35752e7559832ac19d199aa6 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -379,8 +379,8 @@ extern DLLAPI bool silc_debug_hexdump;
 #define SILC_NOT_IMPLEMENTED(string) \
   SILC_LOG_INFO(("*********** %s: NOT IMPLEMENTED YET", string));
 #else
-#define SILC_LOG_DEBUG(fmt)
-#define SILC_NOT_IMPLEMENTED(string)
+#define SILC_LOG_DEBUG(fmt) do { } while(0)
+#define SILC_NOT_IMPLEMENTED(string) do { } while(0)
 #endif /* SILC_DEBUG */
 /***/
 
@@ -413,12 +413,12 @@ extern DLLAPI bool silc_debug_hexdump;
  */
 #if defined(SILC_DEBUG)
 #define SILC_LOG_HEXDUMP(fmt, data, len) silc_log_output_hexdump(__FILE__, \
-                               __FUNCTION__, \
-                               __LINE__, \
-                               (data), (len), \
+                               __FUNCTION__,                              \
+                               __LINE__,                                  \
+                               (void *)(data), (len),                     \
                                silc_format fmt)
 #else
-#define SILC_LOG_HEXDUMP(fmt, data, len)
+#define SILC_LOG_HEXDUMP(fmt, data, len) do { } while(0)
 #endif /* SILC_DEBUG */
 /***/
 
@@ -472,7 +472,7 @@ char *silc_log_get_file(SilcLogType type);
  *
  * SYNOPSIS
  *
- *    bool silc_log_set_file(SilcLogType type, char *filename, 
+ *    bool silc_log_set_file(SilcLogType type, char *filename,
  *                           SilcUInt32 maxsize,
  *                           SilcSchedule scheduler);
  *
@@ -484,8 +484,8 @@ char *silc_log_get_file(SilcLogType type);
  *    logging settings are not changed.
  *
  *    You can disable logging for a channel by specifying NULL filename, the
- *    maxsize in this case is not important.  The `scheduler' parameter is 
- *    needed by the internal logging to allow buffered output and thus to 
+ *    maxsize in this case is not important.  The `scheduler' parameter is
+ *    needed by the internal logging to allow buffered output and thus to
  *    save HD activity.
  *
  ***/
@@ -508,7 +508,7 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
  *    handler.
  *
  *    You can disable/remove a callback by setting it to NULL or calling the
- *    function silc_log_reset_callbacks.  If set, the callback function 
+ *    function silc_log_reset_callbacks.  If set, the callback function
  *    must be in the form described by SilcLogCb.
  *
  * SEE ALSO
@@ -569,7 +569,7 @@ void silc_log_reset_all();
  *
  * SYNOPSIS
  *
- *    void silc_log_output_debug(char *file, char *function,
+ *    void silc_log_output_debug(char *file, const char *function,
  *                               int line, char *string);
  *
  * DESCRIPTION
@@ -581,7 +581,7 @@ void silc_log_reset_all();
  *    dynamic allocated (null-terminated) buffer.
  *
  ***/
-void silc_log_output_debug(char *file, char *function,
+void silc_log_output_debug(char *file, const char *function,
                           int line, char *string);
 
 /****f* silcutil/SilcLogAPI/silc_log_output_hexdump
@@ -602,7 +602,7 @@ void silc_log_output_debug(char *file, char *function,
  *    `string' must be a dynamic allocated (null-terminated) buffer.
  *
  ***/
-void silc_log_output_hexdump(char *file, char *function,
+void silc_log_output_hexdump(char *file, const char *function,
                             int line, void *data_in,
                             SilcUInt32 len, char *string);
 
index 6c213f7a4b1ce73836b8605457e56dfb383afec3..149e8c9044d9f72045ccc78dd82818507eefb7ee 100644 (file)
@@ -122,7 +122,7 @@ void *silc_memdup(const void *ptr, size_t size);
 #else
 #ifndef SILC_DIST_TOOLKIT
 #error "The stack trace is not supported in this distribution"
-#endif
+#endif /* SILC_DIST_TOOLKIT */
 
 #include "stacktrace.h"
 #endif /* SILC_STACKTRACE */
index c25637c08021c4966430656984ec6ece6ea6406f..d083656eba63e379357d64acdc60848ec9aad701 100644 (file)
@@ -292,7 +292,8 @@ bool silc_net_check_host_by_sock(int sock, char **hostname, char **ip)
   struct sockaddr_storage remote;
   char s[NI_MAXHOST];
 
-  *hostname = NULL;
+  if (hostname)
+    *hostname = NULL;
   *ip = NULL;
 
   SILC_LOG_DEBUG(("Resolving remote hostname and IP address"));
@@ -315,7 +316,8 @@ bool silc_net_check_host_by_sock(int sock, char **hostname, char **ip)
   struct sockaddr_in remote;
   char *host_ip;
 
-  *hostname = NULL;
+  if (hostname)
+    *hostname = NULL;
   *ip = NULL;
 
   SILC_LOG_DEBUG(("Resolving remote hostname and IP address"));
@@ -335,19 +337,22 @@ bool silc_net_check_host_by_sock(int sock, char **hostname, char **ip)
     return FALSE;
 #endif
 
-  /* Get host by address */
-  if (!silc_net_gethostbyaddr(*ip, host, sizeof(host)))
-    return FALSE;
+  /* Do reverse lookup if we want hostname too. */
+  if (hostname) {
+    /* Get host by address */
+    if (!silc_net_gethostbyaddr(*ip, host, sizeof(host)))
+      return FALSE;
 
-  *hostname = silc_memdup(host, strlen(host));
-  SILC_LOG_DEBUG(("Resolved hostname `%s'", *hostname));
+    *hostname = silc_memdup(host, strlen(host));
+    SILC_LOG_DEBUG(("Resolved hostname `%s'", *hostname));
 
-  /* Reverse */
-  if (!silc_net_gethostbyname(*hostname, TRUE, host, sizeof(host)))
-    return FALSE;
+    /* Reverse */
+    if (!silc_net_gethostbyname(*hostname, TRUE, host, sizeof(host)))
+      return FALSE;
 
-  if (strcmp(*ip, host))
-    return FALSE;
+    if (strcmp(*ip, host))
+      return FALSE;
+  }
 
   SILC_LOG_DEBUG(("Resolved IP address `%s'", *ip));
   return TRUE;
@@ -365,7 +370,8 @@ bool silc_net_check_local_by_sock(int sock, char **hostname, char **ip)
   struct sockaddr_storage local;
   char s[NI_MAXHOST];
 
-  *hostname = NULL;
+  if (hostname)
+    *hostname = NULL;
   *ip = NULL;
 
   SILC_LOG_DEBUG(("Resolving local hostname and IP address"));
@@ -388,7 +394,8 @@ bool silc_net_check_local_by_sock(int sock, char **hostname, char **ip)
   struct sockaddr_in local;
   char *host_ip;
 
-  *hostname = NULL;
+  if (hostname)
+    *hostname = NULL;
   *ip = NULL;
 
   SILC_LOG_DEBUG(("Resolving local hostname and IP address"));
@@ -408,19 +415,22 @@ bool silc_net_check_local_by_sock(int sock, char **hostname, char **ip)
     return FALSE;
 #endif
 
-  /* Get host by address */
-  if (!silc_net_gethostbyaddr(*ip, host, sizeof(host)))
-    return FALSE;
+  /* Do reverse lookup if we want hostname too. */
+  if (hostname) {
+    /* Get host by address */
+    if (!silc_net_gethostbyaddr(*ip, host, sizeof(host)))
+      return FALSE;
 
-  *hostname = silc_memdup(host, strlen(host));
-  SILC_LOG_DEBUG(("Resolved hostname `%s'", *hostname));
+    *hostname = silc_memdup(host, strlen(host));
+    SILC_LOG_DEBUG(("Resolved hostname `%s'", *hostname));
 
-  /* Reverse */
-  if (!silc_net_gethostbyname(*hostname, TRUE, host, sizeof(host)))
-    return FALSE;
+    /* Reverse */
+    if (!silc_net_gethostbyname(*hostname, TRUE, host, sizeof(host)))
+      return FALSE;
 
-  if (strcmp(*ip, host))
-    return FALSE;
+    if (strcmp(*ip, host))
+      return FALSE;
+  }
 
   SILC_LOG_DEBUG(("Resolved IP address `%s'", *ip));
   return TRUE;
index 5ca563035b4aa6b3008d82a48e04da47628873ac..5ea2ebf00a743da144358d6fd9c506face1902c2 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcschedule.c 
+  silcschedule.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1998 - 2002 Pekka Riikonen
+  Copyright (C) 1998 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@ typedef struct SilcTaskQueueStruct *SilcTaskQueue;
 /* System specific routines. Implemented under unix/, win32/ and such. */
 
 /* System specific select(). Returns same values as normal select(). */
-int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, 
+int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count,
                struct timeval *timeout);
 
 /* Initializes the platform specific scheduler.  This for example initializes
@@ -74,7 +74,7 @@ static void silc_schedule_dispatch_timeout(SilcSchedule schedule,
 static void silc_task_queue_alloc(SilcTaskQueue *queue);
 static void silc_task_queue_free(SilcTaskQueue queue);
 static SilcTask silc_task_find(SilcTaskQueue queue, SilcUInt32 fd);
-static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask, 
+static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask,
                              SilcTaskPriority priority);
 static SilcTask silc_task_get_first(SilcTaskQueue queue, SilcTask first);
 static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
@@ -122,7 +122,7 @@ struct SilcTaskStruct {
 
 /* SILC Task Queue object. The queue holds all the tasks in the scheduler.
    There are always three task queues in the scheduler. One for non-timeout
-   tasks (fd tasks performing tasks over specified file descriptor), 
+   tasks (fd tasks performing tasks over specified file descriptor),
    one for timeout tasks and one for generic tasks. */
 struct SilcTaskQueueStruct {
   SilcTask task;               /* Pointer to all tasks */
@@ -130,10 +130,10 @@ struct SilcTaskQueueStruct {
   SILC_MUTEX_DEFINE(lock);     /* Queue's lock */
 };
 
-/* 
+/*
    SILC Scheduler structure.
 
-   This is the actual schedule object in SILC. Both SILC client and server 
+   This is the actual schedule object in SILC. Both SILC client and server
    uses this same scheduler. Actually, this scheduler could be used by any
    program needing scheduling.
 
@@ -142,7 +142,7 @@ struct SilcTaskQueueStruct {
    SilcTaskQueue fd_queue
 
        Task queue hook for non-timeout tasks. Usually this means that these
-       tasks perform different kind of I/O on file descriptors. File 
+       tasks perform different kind of I/O on file descriptors. File
        descriptors are usually network sockets but they actually can be
        any file descriptors. This hook is initialized in silc_schedule_init
        function. Timeout tasks should not be added to this queue because
@@ -197,7 +197,7 @@ struct SilcTaskQueueStruct {
        System specific scheduler context.
 
    SILC_MUTEX_DEFINE(lock)
-  
+
        Scheduler lock.
 
    bool signal_tasks
@@ -314,15 +314,15 @@ bool silc_schedule_reinit(SilcSchedule schedule, int max_tasks)
   SILC_SCHEDULE_LOCK(schedule);
   if (schedule->max_fd <= max_tasks)
     return FALSE;
-  schedule->fd_list = silc_realloc(schedule->fd_list, 
+  schedule->fd_list = silc_realloc(schedule->fd_list,
                                   (sizeof(*schedule->fd_list) * max_tasks));
   schedule->max_fd = max_tasks;
   SILC_SCHEDULE_UNLOCK(schedule);
   return TRUE;
 }
 
-/* Stops the schedule even if it is not supposed to be stopped yet. 
-   After calling this, one should call silc_schedule_uninit (after the 
+/* Stops the schedule even if it is not supposed to be stopped yet.
+   After calling this, one should call silc_schedule_uninit (after the
    silc_schedule has returned). */
 
 void silc_schedule_stop(SilcSchedule schedule)
@@ -404,7 +404,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
           execution beacuse the task might have been unregistered
           in the callback function, ie. it is not valid anymore. */
 
-       /* Is the task ready for reading */                             
+       /* Is the task ready for reading */
        if (task->valid && revents & SILC_TASK_READ &&
            fd == schedule->fd_list[i].fd) {
          silc_mutex_unlock(schedule->generic_queue->lock);
@@ -415,7 +415,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
          silc_mutex_lock(schedule->generic_queue->lock);
        }
 
-       /* Is the task ready for writing */                             
+       /* Is the task ready for writing */
        if (task->valid && revents & SILC_TASK_WRITE &&
            fd == schedule->fd_list[i].fd) {
          silc_mutex_unlock(schedule->generic_queue->lock);
@@ -445,7 +445,7 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
          break;
 
        task = task->next;
-      }                        
+      }
 
       silc_mutex_unlock(schedule->generic_queue->lock);
     }
@@ -454,8 +454,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
 
 /* Executes all tasks whose timeout has expired. The task is removed from
    the task queue after the callback function has returned. Also, invalid
-   tasks are removed here. We don't have to care about priorities because 
-   tasks are already sorted in their priority order at the registration 
+   tasks are removed here. We don't have to care about priorities because
+   tasks are already sorted in their priority order at the registration
    phase. */
 /* This holds the schedule->lock and the schedule->timeout_queue->lock */
 
@@ -474,7 +474,7 @@ static void silc_schedule_dispatch_timeout(SilcSchedule schedule,
   if (queue && queue->task) {
     task = queue->task;
 
-    /* Walk thorugh all tasks in the particular task queue and run all 
+    /* Walk thorugh all tasks in the particular task queue and run all
        the expired tasks. */
     while(1) {
       /* Execute the task if the timeout has expired */
@@ -599,7 +599,7 @@ bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs)
 
   /* If the task queues aren't initialized or we aren't valid anymore
      we will return */
-  if ((!schedule->fd_queue && !schedule->timeout_queue 
+  if ((!schedule->fd_queue && !schedule->timeout_queue
        && !schedule->generic_queue) || schedule->valid == FALSE) {
     SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting"));
     if (!schedule->is_locked)
@@ -625,7 +625,7 @@ bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs)
      of the selected file descriptors change status or the selected
      timeout expires. */
   SILC_LOG_DEBUG(("Select"));
-  ret = silc_select(schedule->fd_list, schedule->last_fd + 1, 
+  ret = silc_select(schedule->fd_list, schedule->last_fd + 1,
                    schedule->timeout);
 
   SILC_SCHEDULE_LOCK(schedule);
@@ -673,7 +673,7 @@ void silc_schedule(SilcSchedule schedule)
   schedule->is_locked = TRUE;
 
   /* Start the scheduler loop */
-  while (silc_schedule_one(schedule, -1)) 
+  while (silc_schedule_one(schedule, -1))
     ;
 
   SILC_SCHEDULE_UNLOCK(schedule);
@@ -709,9 +709,9 @@ void *silc_schedule_get_context(SilcSchedule schedule)
 /* Add new task to the scheduler */
 
 SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
-                               SilcTaskCallback callback, void *context, 
-                               long seconds, long useconds, 
-                               SilcTaskType type, 
+                               SilcTaskCallback callback, void *context,
+                               long seconds, long useconds,
+                               SilcTaskType type,
                                SilcTaskPriority priority)
 {
   SilcTask newtask;
@@ -722,14 +722,14 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
     return NULL;
 
   queue = SILC_SCHEDULE_GET_QUEUE(type);
-    
+
   /* If the task is generic task, we check whether this task has already
      been registered. Generic tasks are registered only once and after that
      the same task applies to all file descriptors to be registered. */
   if (type == SILC_TASK_GENERIC) {
     silc_mutex_lock(queue->lock);
 
-    SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd, 
+    SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd,
                    type, priority));
 
     if (queue->task) {
@@ -737,7 +737,7 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
       while(1) {
        if ((task->callback == callback) && (task->context == context)) {
          SILC_LOG_DEBUG(("Found matching generic task, using the match"));
-         
+
          silc_mutex_unlock(queue->lock);
 
          /* Add the fd to be listened, the task found now applies to this
@@ -745,10 +745,10 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
          silc_schedule_set_listen_fd(schedule, fd, SILC_TASK_READ, FALSE);
          return task;
        }
-       
+
        if (queue->task == task->next)
          break;
-       
+
        task = task->next;
       }
     }
@@ -827,7 +827,7 @@ void silc_schedule_task_del(SilcSchedule schedule, SilcTask task)
     }
 
     next = queue->task;
-    
+
     while(1) {
       if (next->valid)
        next->valid = FALSE;
@@ -903,6 +903,7 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
     if (schedule->fd_list[i].fd == fd) {
       schedule->fd_list[i].fd = fd;
       schedule->fd_list[i].events = mask;
+      schedule->fd_list[i].revents = 0;
       if (i > schedule->last_fd)
        schedule->last_fd = i;
       found = TRUE;
@@ -918,6 +919,7 @@ void silc_schedule_set_listen_fd(SilcSchedule schedule, SilcUInt32 fd,
       if (schedule->fd_list[i].events == 0) {
        schedule->fd_list[i].fd = fd;
        schedule->fd_list[i].events = mask;
+       schedule->fd_list[i].revents = 0;
        if (i > schedule->last_fd)
          schedule->last_fd = i;
        if (send_events) {
@@ -944,8 +946,9 @@ void silc_schedule_unset_listen_fd(SilcSchedule schedule, SilcUInt32 fd)
     if (schedule->fd_list[i].fd == fd) {
       schedule->fd_list[i].fd = 0;
       schedule->fd_list[i].events = 0;
-      if (schedule->last_fd == i)
-       schedule->last_fd = schedule->max_fd - 1;
+      schedule->fd_list[i].revents = 0;
+      if (schedule->last_fd == i && i > 0)
+       schedule->last_fd = i - 1;
       break;
     }
 
@@ -1019,10 +1022,10 @@ static SilcTask silc_task_find(SilcTaskQueue queue, SilcUInt32 fd)
 }
 
 /* Adds a non-timeout task into the task queue. This function is used
-   by silc_task_register function. Returns a pointer to the registered 
+   by silc_task_register function. Returns a pointer to the registered
    task. */
 
-static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask, 
+static SilcTask silc_task_add(SilcTaskQueue queue, SilcTask newtask,
                              SilcTaskPriority priority)
 {
   SilcTask task, next, prev;
@@ -1102,7 +1105,7 @@ static SilcTask silc_task_get_first(SilcTaskQueue queue, SilcTask first)
 }
 
 /* Adds a timeout task into the task queue. This function is used by
-   silc_task_register function. Returns a pointer to the registered 
+   silc_task_register function. Returns a pointer to the registered
    task. Timeout tasks are sorted by their timeout value in ascending
    order. The priority matters if there are more than one task with
    same timeout. */
@@ -1117,7 +1120,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
 
   /* Take last task from the list */
   prev = task->prev;
-    
+
   switch(priority) {
   case SILC_TASK_PRI_LOW:
     /* Lowest priority. The task is added at the end of the list. */
@@ -1141,7 +1144,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
     newtask->next = next;
     prev->next = newtask;
     next->prev = newtask;
-    
+
     if (prev == task) {
       /* Check if we are going to be the first task in the queue */
       if (silc_compare_timeval(&prev->timeout, &newtask->timeout))
@@ -1177,7 +1180,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
     newtask->next = next;
     prev->next = newtask;
     next->prev = newtask;
-    
+
     if (prev == task) {
       /* Check if we are going to be the first task in the queue */
       if (silc_compare_timeval(&prev->timeout, &newtask->timeout))
@@ -1199,7 +1202,7 @@ static SilcTask silc_task_add_timeout(SilcTaskQueue queue, SilcTask newtask,
 }
 
 /* Removes (unregisters) a task from particular task queue. This function
-   is used internally by scheduler. This must be called holding the 
+   is used internally by scheduler. This must be called holding the
    queue->lock. */
 
 static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task)
@@ -1249,7 +1252,7 @@ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task)
        queue->task = NULL;
       if (queue->task == old)
        queue->task = silc_task_get_first(queue, next);
-      
+
       silc_free(old);
       return TRUE;
     }
index a49422487a0329c1262989edbe2ff790fce95248..9b44b7ed357ae1af084525d0443faba308996fe4 100644 (file)
@@ -4,13 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -40,10 +39,10 @@ typedef struct {
   bool port;
 } *SilcSocketHostLookup;
 
-/* Allocates a new socket connection object. The allocated object is 
+/* Allocates a new socket connection object. The allocated object is
    returned to the new_socket argument. */
 
-void silc_socket_alloc(int sock, SilcSocketType type, void *user_data, 
+void silc_socket_alloc(int sock, SilcSocketType type, void *user_data,
                       SilcSocketConnection *new_socket)
 {
   SILC_LOG_DEBUG(("Allocating new socket connection object"));
@@ -75,7 +74,10 @@ void silc_socket_free(SilcSocketConnection sock)
       silc_schedule_task_del(sock->hb->schedule, sock->hb->hb_task);
       silc_free(sock->hb);
     }
-    silc_free(sock->qos);
+    if (sock->qos) {
+      silc_schedule_task_del_by_context(sock->qos->schedule, sock->qos);
+      silc_free(sock->qos);
+    }
     silc_free(sock->ip);
     silc_free(sock->hostname);
 
@@ -110,7 +112,7 @@ SILC_TASK_CALLBACK(silc_socket_heartbeat)
   if (hb->hb_callback)
     hb->hb_callback(hb->sock, hb->hb_context);
 
-  hb->hb_task = silc_schedule_task_add(hb->schedule, hb->sock->sock, 
+  hb->hb_task = silc_schedule_task_add(hb->schedule, hb->sock->sock,
                                       silc_socket_heartbeat,
                                       context, hb->heartbeat, 0,
                                       SILC_TASK_TIMEOUT,
@@ -125,7 +127,7 @@ SILC_TASK_CALLBACK(silc_socket_heartbeat)
    but will be freed automatically when calling silc_socket_free.  The
    `schedule' is the application's scheduler. */
 
-void silc_socket_set_heartbeat(SilcSocketConnection sock, 
+void silc_socket_set_heartbeat(SilcSocketConnection sock,
                               SilcUInt32 heartbeat,
                               void *hb_context,
                               SilcSocketConnectionHBCb hb_callback,
@@ -156,17 +158,30 @@ void silc_socket_set_heartbeat(SilcSocketConnection sock,
    that is read.  It is guaranteed that silc_socket_read never returns
    more that `read_limit_bytes' of data.  If more is read the limit
    will be applied for the reading.  The `limit_sec' and `limit_usec'
-   specifies the limit that is applied if `read_rate' and/or 
+   specifies the limit that is applied if `read_rate' and/or
    `read_limit_bytes' is reached.  The `schedule' is the application's
    scheduler. */
 
-void silc_socket_set_qos(SilcSocketConnection sock, 
+void silc_socket_set_qos(SilcSocketConnection sock,
                         SilcUInt32 read_rate,
                         SilcUInt32 read_limit_bytes,
                         SilcUInt32 limit_sec,
                         SilcUInt32 limit_usec,
                         SilcSchedule schedule)
 {
+  if (!sock)
+    return;
+
+  if (sock->qos && !read_rate && !read_limit_bytes &&
+      !limit_sec && !limit_usec && !schedule) {
+    silc_schedule_task_del_by_context(sock->qos->schedule, sock->qos);
+    silc_free(sock->qos);
+    sock->qos = NULL;
+    return;
+  }
+  if (!schedule)
+    return;
+
   if (!sock->qos) {
     sock->qos = silc_calloc(1, sizeof(*sock->qos));
     if (!sock->qos)
@@ -179,6 +194,7 @@ void silc_socket_set_qos(SilcSocketConnection sock,
   sock->qos->schedule = schedule;
   memset(&sock->qos->next_limit, 0, sizeof(sock->qos->next_limit));
   sock->qos->cur_rate = 0;
+  sock->qos->sock = sock;
 }
 
 /* Finishing timeout callback that will actually call the user specified
@@ -223,7 +239,7 @@ static void *silc_socket_host_lookup_start(void *context)
   if (lookup->port)
     sock->port = silc_net_get_remote_port(sock->sock);
 
-  silc_net_check_host_by_sock(sock->sock, &sock->hostname, &sock->ip);  
+  silc_net_check_host_by_sock(sock->sock, &sock->hostname, &sock->ip);
   if (!sock->hostname && sock->ip)
     sock->hostname = strdup(sock->ip);
 
index e8f3356cdae300e1c8ae6ea39c0f51461a8808c8..6fcea38d361b8271f4e4b5a2d64be9c953dd6ca7 100644 (file)
@@ -1,16 +1,15 @@
 /*
+
   silcsockconn.h
+
   Author: Pekka Riikonen <priikone@silnet.org>
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+
+  Copyright (C) 1997 - 2001, 2003 Pekka Riikonen
+
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -36,7 +35,7 @@
 /****s* silcutil/SilcSocketConnectionAPI/SilcSocketConnection
  *
  * NAME
- * 
+ *
  *    typedef struct SilcSocketConnectionStruct *SilcSocketConnection;
  *
  * DESCRIPTION
@@ -54,14 +53,14 @@ typedef struct SilcSocketConnectionStruct *SilcSocketConnection;
 /****s* silcutil/SilcSocketConnectionAPI/SilcSocketConnectionHB
  *
  * NAME
- * 
+ *
  *    typedef struct SilcSocketConnectionHB *SilcSocketConnectionHB;
  *
  * DESCRIPTION
  *
  *    This context is the heartbeat context for the SilcSockeConnection.
  *    It is meant to hold the keepalive information for the connection.
- *    This is allocated internally and freed internally by the 
+ *    This is allocated internally and freed internally by the
  *    interface routines.
  *
  ***/
@@ -70,7 +69,7 @@ typedef struct SilcSocketConnectionHBStruct *SilcSocketConnectionHB;
 /****s* silcutil/SilcSocketConnectionAPI/SilcSocketConnectionQos
  *
  * NAME
- * 
+ *
  *    typedef struct SilcSocketConnectionQosStruct *SilcSocketConnectionQos;
  *
  * DESCRIPTION
@@ -90,12 +89,13 @@ typedef struct SilcSocketConnectionQosStruct {
   unsigned int cur_rate : 31;
   unsigned int applied  : 1;
   SilcUInt32 data_len;
+  SilcSocketConnection sock;
 } *SilcSocketConnectionQos;
 
 /****d* silcutil/SilcSocketConnectionAPI/SilcSocketType
  *
  * NAME
- * 
+ *
  *    typedef enum { ... } SilcSocketType;
  *
  * DESCRIPTION
@@ -104,7 +104,7 @@ typedef struct SilcSocketConnectionQosStruct {
  *    are four different types; unknown, client, server and router.
  *    Unknown connections are connections that hasn't advanced long
  *    enough so that we might know which type of connection it is.
- *    It is the applications responsibility to update the type 
+ *    It is the applications responsibility to update the type
  *    information when it becomes available.
  *
  * SOURCE
@@ -131,7 +131,7 @@ typedef enum {
 /****s* silcutil/SilcSocketConnectionAPI/SilcSocketConnectionStruct
  *
  * NAME
- * 
+ *
  *    struct SilcSocketConnectionStruct { ... };
  *
  * DESCRIPTION
@@ -158,7 +158,7 @@ typedef enum {
  *    void *user_data
  *
  *      This is a pointer to a data that is is saved here at the same
- *      time a new connection object is allocated. Usually this is a 
+ *      time a new connection object is allocated. Usually this is a
  *      back-pointer to some important data for fast referencing. For
  *      SILC server this is a pointer to the ID list and for SILC client
  *      to object holding active connections (windows).
@@ -272,7 +272,7 @@ struct SilcSocketConnectionStruct {
  *
  * DESCRIPTION
  *
- *    Allocates a new socket connection object. The allocated object is 
+ *    Allocates a new socket connection object. The allocated object is
  *    returned to the new_socket argument. The `sock' is the socket
  *    for the connection, the `type' the initial type of the connection and
  *    the `user_data' a application specific pointer.
@@ -339,7 +339,7 @@ int silc_socket_read(SilcSocketConnection sock);
  * DESCRIPTION
  *
  *    Writes data from the outgoing buffer to the socket connection. If the
- *    data cannot be written at once, it must be written at later time. 
+ *    data cannot be written at once, it must be written at later time.
  *    The data is written from the data section of the buffer, not from head
  *    or tail section. This automatically pulls the data section towards end
  *    after writing the data. Implementation of this function may be
@@ -386,7 +386,7 @@ typedef void (*SilcSocketConnectionHBCb)(SilcSocketConnection sock,
  *
  * SYNOPSIS
  *
- *    void silc_socket_set_heartbeat(SilcSocketConnection sock, 
+ *    void silc_socket_set_heartbeat(SilcSocketConnection sock,
  *                                   SilcUInt32 heartbeat,
  *                                   void *hb_context,
  *                                   SilcSocketConnectionHBCb hb_callback,
@@ -403,7 +403,7 @@ typedef void (*SilcSocketConnectionHBCb)(SilcSocketConnection sock,
  *    application's scheduler.
  *
  ***/
-void silc_socket_set_heartbeat(SilcSocketConnection sock, 
+void silc_socket_set_heartbeat(SilcSocketConnection sock,
                               SilcUInt32 heartbeat,
                               void *hb_context,
                               SilcSocketConnectionHBCb hb_callback,
@@ -413,7 +413,7 @@ void silc_socket_set_heartbeat(SilcSocketConnection sock,
  *
  * SYNOPSIS
  *
- *    void silc_socket_set_qos(SilcSocketConnection sock, 
+ *    void silc_socket_set_qos(SilcSocketConnection sock,
  *                             SilcUInt32 read_rate,
  *                             SilcUInt32 read_limit_bytes,
  *                             SilcUInt32 limit_sec,
@@ -429,12 +429,14 @@ void silc_socket_set_heartbeat(SilcSocketConnection sock,
  *    that is read.  It is guaranteed that silc_socket_read never returns
  *    more that `read_limit_bytes' of data.  If more is read the limit
  *    will be applied for the reading.  The `limit_sec' and `limit_usec'
- *    specifies the limit that is applied if `read_rate' and/or 
+ *    specifies the limit that is applied if `read_rate' and/or
  *    `read_limit_bytes' is reached.  The `schedule' is the application's
- *    scheduler.
+ *    scheduler.  If all arguments except `sock' are NULL or zero this
+ *    resets the QoS from the socket, all QoS for this socket that may
+ *    be pending will be cancelled.
  *
  ***/
-void silc_socket_set_qos(SilcSocketConnection sock, 
+void silc_socket_set_qos(SilcSocketConnection sock,
                         SilcUInt32 read_rate,
                         SilcUInt32 read_limit_bytes,
                         SilcUInt32 limit_sec,
@@ -474,16 +476,16 @@ typedef void (*SilcSocketHostLookupCb)(SilcSocketConnection sock,
  *    connection is created and the full IP address and fully qualified
  *    domain name information is desired. The `callback' with `context'
  *    will be called after the lookup is performed. The `schedule'
- *    is the application's scheduler which the lookup routine needs. 
+ *    is the application's scheduler which the lookup routine needs.
  *    If the socket connection is freed during the lookup the library
  *    will automatically cancel the lookup and the `callback' will not be
  *    called.
  *
- *    If `port_lookup' is TRUE then the remote port of the socket 
+ *    If `port_lookup' is TRUE then the remote port of the socket
  *    connection is resolved. After the information is resolved they
  *    are accessible using sock->ip and sock->hostname pointers. Note
  *    that if the both IP and FQDN could not be resolved the sock->hostname
- *    includes the IP address of the remote host. The resolved port is 
+ *    includes the IP address of the remote host. The resolved port is
  *    available in sock->port.
  *
  ***/
diff --git a/lib/silcutil/silcstringprep.c b/lib/silcutil/silcstringprep.c
new file mode 100644 (file)
index 0000000..aa2119e
--- /dev/null
@@ -0,0 +1,269 @@
+/*
+
+  silcstringprep.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 - 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcstringprep.h"
+#include <stringprep.h>
+
+/* We use GNU Libidn which has stringprep to do the magic.  Only bad thing
+   is that its interface is idiotic.  We have our own API here in case
+   we'll implement it ourselves later. */
+
+/* Prohibited characters as defined by the protocol in Appendix C */
+const Stringprep_table_element silc_appendix_c[] =
+{
+  {0x000021}, {0x00002A}, {0x00002C}, {0x00003F}, {0x000040},
+  {0}
+};
+
+/* Prohibited characters as defined by the protocol in Appendix D */
+const Stringprep_table_element silc_appendix_d[] =
+{
+  {0x0000A2, 0x0000A9},
+  {0x0000AC}, {0x0000AE}, {0x0000AF}, {0x0000B0}, {0x0000B1}, {0x0000B4},
+  {0x0000B6}, {0x0000B8}, {0x0000D7}, {0x0000F7},
+  {0x0002C2, 0x0002C5}, {0x0002D2, 0x0002FF},
+  {0x000374}, {0x000375}, {0x000384}, {0x000385}, {0x0003F6}, {0x000482},
+  {0x00060E}, {0x00060F}, {0x0006E9}, {0x0006FD}, {0x0006FE}, {0x0009F2},
+  {0x0009F3}, {0x0009FA}, {0x000AF1}, {0x000B70},
+  {0x000BF3, 0x000BFA}, {0x000E3F},
+  {0x000F01, 0x000F03}, {0x000F13, 0x000F17}, {0x000F1A, 0x000F1F},
+  {0x000F34}, {0x000F36}, {0x000F38}, {0x000FBE}, {0x000FBF},
+  {0x000FC0, 0x000FC5}, {0x000FC7, 0x000FCF}, {0x0017DB}, {0x001940},
+  {0x0019E0, 0x0019FF}, {0x001FBD}, {0x001FBF, 0x001FC1},
+  {0x001FCD, 0x001FCF}, {0x001FDD, 0x001FDF}, {0x001FED, 0x001FEF},
+  {0x001FFD}, {0x001FFE}, {0x002044}, {0x002052}, {0x00207A, 0x00207C},
+  {0x00208A, 0x00208C}, {0x0020A0, 0x0020B1}, {0x002100, 0x00214F},
+  {0x002150, 0x00218F}, {0x002190, 0x0021FF}, {0x002200, 0x0022FF},
+  {0x002300, 0x0023FF}, {0x002400, 0x00243F}, {0x002440, 0x00245F},
+  {0x002460, 0x0024FF}, {0x002500, 0x00257F}, {0x002580, 0x00259F},
+  {0x0025A0, 0x0025FF}, {0x002600, 0x0026FF}, {0x002700, 0x0027BF},
+  {0x0027C0, 0x0027EF}, {0x0027F0, 0x0027FF}, {0x002800, 0x0028FF},
+  {0x002900, 0x00297F}, {0x002980, 0x0029FF}, {0x002A00, 0x002AFF},
+  {0x002B00, 0x002BFF}, {0x002E9A}, {0x002EF4, 0x002EFF},
+  {0x002FF0, 0x002FFF}, {0x00303B, 0x00303D}, {0x003040},
+  {0x003095, 0x003098}, {0x00309F, 0x0030A0}, {0x0030FF, 0x003104},
+  {0x00312D, 0x003130}, {0x00318F}, {0x0031B8, 0x0031FF},
+  {0x00321D, 0x00321F}, {0x003244, 0x00325F}, {0x00327C, 0x00327E},
+  {0x0032B1, 0x0032BF}, {0x0032CC, 0x0032CF}, {0x0032FF},
+  {0x003377, 0x00337A}, {0x0033DE, 0x0033DF}, {0x0033FF},
+  {0x004DB6, 0x004DFF},
+  {0x009FA6, 0x009FFF}, {0x00A48D, 0x00A48F}, {0x00A4A2, 0x00A4A3},
+  {0x00A4B4}, {0x00A4C1}, {0x00A4C5}, {0x00A4C7, 0x00ABFF},
+  {0x00D7A4, 0x00D7FF}, {0x00FA2E, 0x00FAFF}, {0x00FFE0, 0x00FFEE},
+  {0x00FFFC}, {0x010000, 0x01007F}, {0x010080, 0x0100FF},
+  {0x010100, 0x01013F}, {0x01D000, 0x01D0FF}, {0x01D100, 0x01D1FF},
+  {0x01D300, 0x01D35F}, {0x01D400, 0x01D7FF},
+  {0x0E0100, 0x0E01EF},
+  {0}
+};
+
+/* Default SILC Identifier String profile defined by the protocol */
+const Stringprep_profile stringprep_silc_identifier_prep[] =
+{
+  {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_rfc3454_C_9},
+  {STRINGPREP_PROHIBIT_TABLE, 0, silc_appendix_c},
+  {STRINGPREP_PROHIBIT_TABLE, 0, silc_appendix_d},
+  {STRINGPREP_UNASSIGNED_TABLE, 0, stringprep_rfc3454_A_1},
+  {0}
+};
+
+/* Default channel name string profile defined by the protocol */
+const Stringprep_profile stringprep_silc_identifier_ch_prep[] =
+{
+  {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_rfc3454_C_9},
+  {STRINGPREP_PROHIBIT_TABLE, 0, silc_appendix_d},
+  {STRINGPREP_UNASSIGNED_TABLE, 0, stringprep_rfc3454_A_1},
+  {0}
+};
+
+/* Identifier string case folding and normalizing */
+const Stringprep_profile stringprep_silc_identifierc_prep[] =
+{
+  {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_1},
+  {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
+  {STRINGPREP_NFKC, 0, 0},
+  {0}
+};
+
+/* Case folding and normalizing */
+const Stringprep_profile stringprep_silc_casefold_prep[] =
+{
+  {STRINGPREP_MAP_TABLE, 0, stringprep_rfc3454_B_2},
+  {STRINGPREP_NFKC, 0, 0},
+  {0}
+};
+
+
+/* Prepares string according to the profile */
+
+SilcStringprepStatus
+silc_stringprep(const unsigned char *bin, SilcUInt32 bin_len,
+               SilcStringEncoding bin_encoding,
+               const char *profile_name,
+               SilcStringprepFlags flags,
+               unsigned char **out, SilcUInt32 *out_len,
+               SilcStringEncoding out_encoding)
+{
+  Stringprep_profile_flags f = 0;
+  const Stringprep_profile *profile;
+  unsigned char *utf8s;
+  SilcUInt32 utf8s_len;
+  int ret;
+
+  SILC_LOG_DEBUG(("Preparing string"));
+
+  if (!bin || !bin_len || !profile_name)
+    return SILC_STRINGPREP_ERR;
+
+  /* Convert string to UTF-8 */
+  utf8s_len = silc_utf8_encoded_len(bin, bin_len, bin_encoding);
+  if (!utf8s_len)
+    return SILC_STRINGPREP_ERR_ENCODING;
+  utf8s = silc_calloc(utf8s_len + 1, sizeof(*utf8s));
+  if (!utf8s)
+    return SILC_STRINGPREP_ERR_OUT_OF_MEMORY;
+  silc_utf8_encode(bin, bin_len, bin_encoding, utf8s, utf8s_len);
+
+  /* Check profile. */
+  if (!strcmp(profile_name, SILC_IDENTIFIER_PREP))
+    profile = stringprep_silc_identifier_prep;
+  else if (!strcmp(profile_name, SILC_IDENTIFIER_CH_PREP))
+    profile = stringprep_silc_identifier_ch_prep;
+  else if (!strcmp(profile_name, SILC_IDENTIFIERC_PREP))
+    profile = stringprep_silc_identifierc_prep;
+  else if (!strcmp(profile_name, SILC_CASEFOLD_PREP))
+    profile = stringprep_silc_casefold_prep;
+  else
+    return SILC_STRINGPREP_ERR_UNSUP_PROFILE;
+
+  /* Translate flags */
+  if (!(flags & SILC_STRINGPREP_ALLOW_UNASSIGNED))
+    f |= STRINGPREP_NO_UNASSIGNED;
+
+  /* Prepare */
+  ret = stringprep((char *)utf8s, utf8s_len + 1, f, profile);
+  SILC_LOG_DEBUG(("stringprep() return %d", ret));
+
+  /* Since the stringprep() doesn't allocate returned buffer, and
+     stringprep_profile() doesn't do it correctly, we can't know how
+     much space we must have for the conversion.  Allocate more if it
+     fails, and try again. */
+  if (ret == STRINGPREP_TOO_SMALL_BUFFER) {
+    utf8s = silc_realloc(utf8s, sizeof(*utf8s) * (utf8s_len * 2));
+    if (!utf8s)
+      return SILC_STRINGPREP_ERR_OUT_OF_MEMORY;
+    memset(utf8s + utf8s_len, 0, utf8s_len);
+    ret = stringprep((char *)utf8s, utf8s_len * 2, f, profile);
+    SILC_LOG_DEBUG(("stringprep() return %d", ret));
+  }
+
+  switch (ret) {
+  case STRINGPREP_OK:
+    ret = SILC_STRINGPREP_OK;
+    break;
+
+  case STRINGPREP_CONTAINS_UNASSIGNED:
+    ret = SILC_STRINGPREP_ERR_UNASSIGNED;
+    break;
+
+  case STRINGPREP_CONTAINS_PROHIBITED:
+    ret = SILC_STRINGPREP_ERR_PROHIBITED;
+    break;
+
+  case STRINGPREP_BIDI_BOTH_L_AND_RAL:
+    ret = SILC_STRINGPREP_ERR_BIDI_RAL_WITH_L;
+    break;
+
+  case STRINGPREP_BIDI_LEADTRAIL_NOT_RAL:
+    ret = SILC_STRINGPREP_ERR_BIDI_RAL;
+    break;
+
+  case STRINGPREP_BIDI_CONTAINS_PROHIBITED:
+    ret = SILC_STRINGPREP_ERR_BIDI_PROHIBITED;
+    break;
+
+  case STRINGPREP_UNKNOWN_PROFILE:
+    ret = SILC_STRINGPREP_ERR_UNSUP_PROFILE;
+    break;
+
+  case STRINGPREP_MALLOC_ERROR:
+    ret = SILC_STRINGPREP_ERR_OUT_OF_MEMORY;
+    break;
+
+  default:
+    ret = SILC_STRINGPREP_ERR;
+    break;
+  }
+
+  /* Convert to desired output character encoding */
+  if (ret == SILC_STRINGPREP_OK) {
+    if (out && out_len) {
+      if (out_encoding != SILC_STRING_UTF8) {
+       *out_len = silc_utf8_decoded_len(utf8s, strlen(utf8s), out_encoding);
+       if (*out_len) {
+         *out = silc_calloc(*out_len + 1, sizeof(**out));
+         if (*out) {
+           silc_utf8_decode(utf8s, strlen(utf8s), out_encoding, *out,
+                            *out_len);
+         } else {
+           ret = SILC_STRINGPREP_ERR_OUT_OF_MEMORY;
+         }
+       } else {
+         ret = SILC_STRINGPREP_ERR_ENCODING;
+       }
+      } else {
+       *out_len = strlen(utf8s);
+       *out = silc_memdup(utf8s, *out_len);
+      }
+    }
+  }
+
+  silc_free(utf8s);
+
+  return (SilcStringprepStatus)ret;
+}
diff --git a/lib/silcutil/silcstringprep.h b/lib/silcutil/silcstringprep.h
new file mode 100644 (file)
index 0000000..21bc331
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+
+  silcstringprep.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 - 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+/****h* silcutil/SILC Stringprep
+ *
+ * DESCRIPTION
+ *
+ * Interface for the stringprep (RFC3454) standard, that is used to prepare
+ * strings for internationalization.  The interface can be used to prepare
+ * strings according to various stringprep profiles.  The profiles defines
+ * what characters the strings may contain, what characters are prohibited
+ * and how the strings are prepared.
+ *
+ ***/
+
+#ifndef SILCSTRINGPREP_H
+#define SILCSTRINGPREP_H
+
+/****d* silcutil/SilcStringprep/SilcStringprepStatus
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcStringprepStatus;
+ *
+ * DESCRIPTION
+ *
+ *    Status and errors returned by silc_stringprep.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_STRINGPREP_OK,                    /* Preparation success */
+  SILC_STRINGPREP_ERR_UNASSIGNED,         /* Contains unassigned characters */
+  SILC_STRINGPREP_ERR_PROHIBITED,        /* Contains prohibited characters */
+  SILC_STRINGPREP_ERR_BIDI_PROHIBITED,   /* BIDI contains prohibited chars */
+  SILC_STRINGPREP_ERR_BIDI_RAL_WITH_L,   /* BIDI has both R/AL and L */
+  SILC_STRINGPREP_ERR_BIDI_RAL,                  /* BIDI has R/AL but not as leading
+                                            and/or trailing character. */
+  SILC_STRINGPREP_ERR_OUT_OF_MEMORY,     /* System out of memory */
+  SILC_STRINGPREP_ERR_ENCODING,                  /* Character encoding error */
+  SILC_STRINGPREP_ERR_UNSUP_ENCODING,     /* Unsupported character encoding  */
+  SILC_STRINGPREP_ERR_UNSUP_PROFILE,     /* Unsupported profile */
+  SILC_STRINGPREP_ERR,                   /* Unknown error */
+} SilcStringprepStatus;
+/***/
+
+/****d* silcutil/SilcStringprep/SilcStringprepFlags
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcStringprepFlags;
+ *
+ * DESCRIPTION
+ *
+ *    Flags that change how the strings are prepared with silc_stringprep.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_STRINGPREP_NONE               = 0x00,  /* No flags */
+  SILC_STRINGPREP_ALLOW_UNASSIGNED   = 0x01,  /* Allow unassigned characters
+                                                without returning error. */
+} SilcStringprepFlags;
+/***/
+
+/* Profiles */
+#define SILC_IDENTIFIER_PREP "silc-identifier-prep"
+#define SILC_IDENTIFIERC_PREP "silc-identifierc-prep"
+#define SILC_IDENTIFIER_CH_PREP "silc-identifier-ch-prep"
+#define SILC_CASEFOLD_PREP "silc-casefold-prep"
+
+/****f* silcutil/SilcStringprep/silc_stringprep
+ *
+ * SYNOPSIS
+ *
+ *    SilcStringprepStatus
+ *    silc_stringprep(const unsigned char *bin, SilcUInt32 bin_len,
+ *                    SilcStringEncoding bin_encoding,
+ *                    const char *profile_name,
+ *                    SilcStringprepFlags flags,
+ *                    unsigned char **out, SilcUInt32 *out_len,
+ *                    SilcStringEncoding out_encoding);
+ *
+ * DESCRIPTION
+ *
+ *    Prepares the input string 'bin' of length 'bin_len' of encoding
+ *    'bin_encoding' according to the stringrep profile 'profile_name'.
+ *    Returns the prepared and allocated string into 'out'.  The 'out_len'
+ *    indicates the length of the prepared string.  This returns the
+ *    SilcStringprepStatus which indicates the status of the preparation.
+ *    For example, if the input string contains prohibited characters
+ *    (according to the used profile) this function will return error.
+ *    The 'flags' however can be used to modify the behavior of this
+ *    function.  Caller must free the returned 'out' string.
+ *
+ *    The output string will be encoded into the character encoding
+ *    defined by the 'out_encoding'.  This allows caller to have for
+ *    example the input string as locale specific string and output string
+ *    as UTF-8 encoded string.
+ *
+ *    If the 'out' is NULL this function merely performs the preparation
+ *    process, but does not return anything.  In this case this function
+ *    could be used to for example verify that an input string that ought
+ *    to have been prepared correctly was done so.
+ *
+ *    Available profile names:
+ *
+ *      SILC_IDENTIFIER_PREP            Prepares SILC identifier strings
+ *      SILC_IDENTIFIER_CH_PREP         Prepares SILC channel name strings
+ *      SILC_IDENTIFIERC_PREP           Casefolds identifier strings
+ *      SILC_CASEFOLD_PREP              Casefolding and normalizing
+ *
+ ***/
+SilcStringprepStatus
+silc_stringprep(const unsigned char *bin, SilcUInt32 bin_len,
+               SilcStringEncoding bin_encoding,
+               const char *profile_name,
+               SilcStringprepFlags flags,
+               unsigned char **out, SilcUInt32 *out_len,
+               SilcStringEncoding out_encoding);
+
+#endif /* SILCSTRINGPREP_H */
index de215d60bb6957aa744536acd020efb59922750b..c387ffc4fe012b4a0136455f115f4731890a420d 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcstrutil.c 
+  silcstrutil.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 - 2003 Pekka Riikonen
+  Copyright (C) 2002 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -170,360 +170,6 @@ unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len,
   return data;
 }
 
-/* Encodes the string `bin' of which encoding is `bin_encoding' to the
-   UTF-8 encoding into the buffer `utf8' which is of size of `utf8_size'.
-   Returns the length of the UTF-8 encoded string, or zero (0) on error.
-   By default `bin_encoding' is ASCII, and the caller needs to know the
-   encoding of the input string if it is anything else. */
-
-SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
-                           SilcStringEncoding bin_encoding,
-                           unsigned char *utf8, SilcUInt32 utf8_size)
-{
-  SilcUInt32 enclen = 0, i, charval = 0;
-
-  if (!bin || !bin_len)
-    return 0;
-
-  if (silc_utf8_valid(bin, bin_len) && bin_len <= utf8_size) {
-    memcpy(utf8, bin, bin_len);
-    return bin_len;
-  }
-
-  if (bin_encoding == SILC_STRING_LANGUAGE) {
-#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
-    char *fromconv, *icp, *ocp;
-    iconv_t icd;
-    size_t inlen, outlen;
-
-    setlocale(LC_CTYPE, "");
-    fromconv = nl_langinfo(CODESET);
-    if (fromconv && strlen(fromconv)) {
-      icd = iconv_open("UTF-8", fromconv);
-      icp = (char *)bin;
-      ocp = (char *)utf8;
-      inlen = bin_len;
-      outlen = utf8_size;
-      if (icp && ocp && icd != (iconv_t)-1) {
-       if (iconv(icd, &icp, &inlen, &ocp, &outlen) != -1) {
-         utf8_size -= outlen;
-         iconv_close(icd);
-         return utf8_size;
-       }
-      }
-      if (icd != (iconv_t)-1)
-       iconv_close(icd);
-    }
-#endif
-
-    /* Fallback to 8-bit ASCII */
-    bin_encoding = SILC_STRING_ASCII;
-  }
-
-  for (i = 0; i < bin_len; i++) {
-    switch (bin_encoding) {
-    case SILC_STRING_ASCII:
-      charval = bin[i];
-      break;
-    case SILC_STRING_ASCII_ESC:
-      SILC_NOT_IMPLEMENTED("SILC_STRING_ASCII_ESC");
-      return 0;
-      break;
-    case SILC_STRING_BMP:
-      if (i + 1 >= bin_len)
-       return 0;
-      SILC_GET16_MSB(charval, bin + i);
-      i += 1;
-      break;
-    case SILC_STRING_BMP_LSB:
-      if (i + 1 >= bin_len)
-       return 0;
-      SILC_GET16_LSB(charval, bin + i);
-      i += 1;
-      break;
-    case SILC_STRING_UNIVERSAL:
-      if (i + 3 >= bin_len)
-       return 0;
-      SILC_GET32_MSB(charval, bin + i);
-      i += 3;
-      break;
-    case SILC_STRING_UNIVERSAL_LSB:
-      if (i + 3 >= bin_len)
-       return 0;
-      SILC_GET32_LSB(charval, bin + i);
-      i += 3;
-      break;
-    default:
-      return 0;
-      break;
-    }
-
-    if (charval < 0x80) {
-      if (utf8) {
-       if (enclen > utf8_size)
-         return 0;
-
-       utf8[enclen] = (unsigned char)charval;
-      }
-      enclen++;
-    } else if (charval < 0x800) {
-      if (utf8) {
-       if (enclen + 2 > utf8_size)
-         return 0;
-
-       utf8[enclen    ] = (unsigned char )(((charval >> 6)  & 0x1f) | 0xc0);
-       utf8[enclen + 1] = (unsigned char )((charval & 0x3f) | 0x80);
-      }
-      enclen += 2;
-    } else if (charval < 0x10000) {
-      if (utf8) {
-       if (enclen + 3 > utf8_size)
-         return 0;
-
-       utf8[enclen    ] = (unsigned char )(((charval >> 12) & 0xf)  | 0xe0);
-       utf8[enclen + 1] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
-       utf8[enclen + 2] = (unsigned char )((charval & 0x3f) | 0x80);
-      }
-      enclen += 3;
-    } else if (charval < 0x200000) {
-      if (utf8) {
-       if (enclen + 4 > utf8_size)
-         return 0;
-
-       utf8[enclen    ] = (unsigned char )(((charval >> 18) & 0x7)  | 0xf0);
-       utf8[enclen + 1] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
-       utf8[enclen + 2] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
-       utf8[enclen + 3] = (unsigned char )((charval & 0x3f) | 0x80);
-      }
-      enclen += 4;
-    } else if (charval < 0x4000000) {
-      if (utf8) {
-       if (enclen + 5 > utf8_size)
-         return 0;
-
-       utf8[enclen    ] = (unsigned char )(((charval >> 24) & 0x3)  | 0xf8);
-       utf8[enclen + 1] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80);
-       utf8[enclen + 2] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
-       utf8[enclen + 3] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
-       utf8[enclen + 4] = (unsigned char )((charval & 0x3f) | 0x80);
-      }
-      enclen += 5;
-    } else {
-      if (utf8) {
-       if (enclen + 6 > utf8_size)
-         return 0;
-
-       utf8[enclen    ] = (unsigned char )(((charval >> 30) & 0x1)  | 0xfc);
-       utf8[enclen + 1] = (unsigned char )(((charval >> 24) & 0x3f) | 0x80);
-       utf8[enclen + 2] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80);
-       utf8[enclen + 3] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
-       utf8[enclen + 4] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
-       utf8[enclen + 5] = (unsigned char )((charval & 0x3f) | 0x80);
-      }
-      enclen += 6;
-    }
-  }
-
-  return enclen;
-}
-
-/* Decodes UTF-8 encoded string `utf8' to string of which encoding is
-   to be `bin_encoding', into the `bin' buffer of size of `bin_size'.
-   Returns the length of the decoded buffer, or zero (0) on error.
-   By default `bin_encoding' is ASCII, and the caller needs to know to
-   which encoding the output string is to be encoded if ASCII is not
-   desired. */
-
-SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
-                           SilcStringEncoding bin_encoding,
-                           unsigned char *bin, SilcUInt32 bin_size)
-{
-  SilcUInt32 enclen = 0, i, charval;
-
-  if (!utf8 || !utf8_len)
-    return 0;
-
-  if (bin_encoding == SILC_STRING_LANGUAGE) {
-#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
-    char *toconv, *icp, *ocp;
-    iconv_t icd;
-    size_t inlen, outlen;
-
-    setlocale(LC_CTYPE, "");
-    toconv = nl_langinfo(CODESET);
-    if (toconv && strlen(toconv)) {
-      icd = iconv_open(toconv, "UTF-8");
-      icp = (char *)utf8;
-      ocp = (char *)bin;
-      inlen = utf8_len;
-      outlen = bin_size;
-      if (icp && ocp && icd != (iconv_t)-1) {
-       if (iconv(icd, &icp, &inlen, &ocp, &outlen) != -1) {
-         bin_size -= outlen;
-         iconv_close(icd);
-         return bin_size;
-       }
-      }
-      if (icd != (iconv_t)-1)
-       iconv_close(icd);
-    }
-#endif
-
-    /* Fallback to 8-bit ASCII */
-    bin_encoding = SILC_STRING_ASCII;
-  }
-
-  for (i = 0; i < utf8_len; i++) {
-    if ((utf8[i] & 0x80) == 0x00) {
-      charval = utf8[i] & 0x7f;
-    } else if ((utf8[i] & 0xe0) == 0xc0) {
-      if (i + 1 >= utf8_len)
-       return 0;
-
-      if ((utf8[i + 1] & 0xc0) != 0x80)
-        return 0;
-
-      charval = (utf8[i++] & 0x1f) << 6;
-      charval |= utf8[i] & 0x3f;
-      if (charval < 0x80)
-        return 0;
-    } else if ((utf8[i] & 0xf0) == 0xe0) {
-      if (i + 2 >= utf8_len)
-       return 0;
-
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
-         ((utf8[i + 2] & 0xc0) != 0x80))
-        return 0;
-
-      charval = (utf8[i++]  & 0xf)  << 12;
-      charval |= (utf8[i++] & 0x3f) << 6;
-      charval |= utf8[i] & 0x3f;
-      if (charval < 0x800)
-        return 0;
-    } else if ((utf8[i] & 0xf8) == 0xf0) {
-      if (i + 3 >= utf8_len)
-       return 0;
-
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
-         ((utf8[i + 2] & 0xc0) != 0x80) ||
-         ((utf8[i + 3] & 0xc0) != 0x80))
-        return 0;
-
-      charval = ((SilcUInt32)(utf8[i++] & 0x7)) << 18;
-      charval |= (utf8[i++] & 0x3f) << 12;
-      charval |= (utf8[i++] & 0x3f) << 6;
-      charval |= utf8[i] & 0x3f;
-      if (charval < 0x10000)
-        return 0;
-    } else if ((utf8[i] & 0xfc) == 0xf8) {
-      if (i + 4 >= utf8_len)
-       return 0;
-
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
-         ((utf8[i + 2] & 0xc0) != 0x80) ||
-         ((utf8[i + 3] & 0xc0) != 0x80) ||
-         ((utf8[i + 4] & 0xc0) != 0x80))
-        return 0;
-
-      charval = ((SilcUInt32)(utf8[i++]  & 0x3))  << 24;
-      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18;
-      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12;
-      charval |= (utf8[i++] & 0x3f) << 6;
-      charval |= utf8[i] & 0x3f;
-      if (charval < 0x200000)
-        return 0;
-    } else if ((utf8[i] & 0xfe) == 0xfc) {
-      if (i + 5 >= utf8_len)
-       return 0;
-
-      if (((utf8[i + 1] & 0xc0) != 0x80) || 
-         ((utf8[i + 2] & 0xc0) != 0x80) ||
-         ((utf8[i + 3] & 0xc0) != 0x80) ||
-         ((utf8[i + 4] & 0xc0) != 0x80) ||
-         ((utf8[i + 5] & 0xc0) != 0x80))
-        return 0;
-
-      charval = ((SilcUInt32)(utf8[i++]  & 0x1))  << 30;
-      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 24;
-      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18;
-      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12;
-      charval |= (utf8[i++] & 0x3f) << 6;
-      charval |= utf8[i] & 0x3f;
-      if (charval < 0x4000000)
-        return 0;
-    } else {
-      return 0;
-    }
-
-    switch (bin_encoding) {
-    case SILC_STRING_ASCII:
-      if (bin) {
-        if (enclen + 1 > bin_size)
-          return 0;
-
-        bin[enclen] = (unsigned char)charval;
-      }
-      enclen++;
-      break;
-    case SILC_STRING_ASCII_ESC:
-      SILC_NOT_IMPLEMENTED("SILC_STRING_ASCII_ESC");
-      return 0;
-      break;
-    case SILC_STRING_BMP:
-      if (bin)
-       SILC_PUT16_MSB(charval, bin + enclen);
-      enclen += 2;
-      break;
-    case SILC_STRING_BMP_LSB:
-      if (bin)
-       SILC_PUT16_LSB(charval, bin + enclen);
-      enclen += 2;
-      break;
-    case SILC_STRING_UNIVERSAL:
-      if (bin)
-       SILC_PUT32_MSB(charval, bin + enclen);
-      enclen += 4;
-      break;
-    case SILC_STRING_UNIVERSAL_LSB:
-      if (bin)
-       SILC_PUT32_LSB(charval, bin + enclen);
-      enclen += 4;
-      break;
-    default:
-      return 0;
-      break;
-    }
-  }
-
-  return enclen;
-}
-
-/* Returns the length of UTF-8 encoded string if the `bin' of
-   encoding of `bin_encoding' is encoded with silc_utf8_encode. */
-
-SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len,
-                                SilcStringEncoding bin_encoding)
-{
-  return silc_utf8_encode(bin, bin_len, bin_encoding, NULL, 0);
-}
-
-/* Returns the length of decoded string if the `bin' of encoding of
-   `bin_encoding' is decoded with silc_utf8_decode. */
-
-SilcUInt32 silc_utf8_decoded_len(const unsigned char *bin, SilcUInt32 bin_len,
-                                SilcStringEncoding bin_encoding)
-{
-  return silc_utf8_decode(bin, bin_len, bin_encoding, NULL, 0);
-}
-
-/* Returns TRUE if the `utf8' string of length of `utf8_len' is valid
-   UTF-8 encoded string, FALSE if it is not UTF-8 encoded string. */
-
-bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len)
-{
-  return silc_utf8_decode(utf8, utf8_len, 0, NULL, 0) != 0;
-}
-
 /* Mime constants and macros */
 #define MIME_VERSION "MIME-Version: "
 #define MIME_VERSION_LEN 14
@@ -532,15 +178,24 @@ bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len)
 #define MIME_TRANSFER_ENCODING "Content-Transfer-Encoding: "
 #define MIME_TRANSFER_ENCODING_LEN 27
 
-#define MIME_GET_FIELD(header, mime, mime_len, field, field_len,       \
+#define MIME_GET_FIELD(mime, mime_len, field, field_len,               \
                       dest, dest_size)                                 \
 do {                                                                   \
   if (dest) {                                                          \
-    char *f = strstr(header, field);                                   \
+    char *f = strstr(mime, field);                                     \
     if (f) {                                                           \
-      f = (char *)mime + (f - header) + field_len;                     \
-      for (i = 0; i < (mime_len - (f - (char *)mime)); i++) {          \
-        if (f[i] == '\r' || f[i] == '\n' || i == dest_size)            \
+      int parse_len;                                                   \
+      f += field_len;                                                  \
+      parse_len = (mime_len - (f - (char *)mime));                     \
+      for (i = 0; i < parse_len; i++) {                                        \
+        if ((i == dest_size) ||                                                \
+           ((f[i] == '\n') &&                                          \
+              ((i == parse_len - 1) ||                                 \
+                 ((f[i+1] != ' ') && (f[i+1] != '\t')))) ||            \
+           ((f[i] == '\r') &&                                          \
+              ((i == parse_len - 1) || (f[i+1] == '\n')) &&            \
+              ((i >= parse_len - 2) ||                                 \
+                 ((f[i+2] != ' ') && (f[i+2] != '\t')))))              \
           break;                                                       \
         dest[i] = f[i];                                                        \
       }                                                                        \
@@ -550,46 +205,47 @@ do {                                                                      \
 
 /* Parses MIME object and MIME header in it. */
 
-bool 
+bool
 silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
                 char *version, SilcUInt32 version_size,
                 char *content_type, SilcUInt32 content_type_size,
                 char *transfer_encoding, SilcUInt32 transfer_encoding_size,
                 unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len)
-{ 
+{
   int i;
-  char header[256];
-   
-  memcpy(header, mime, 256 > mime_len ? mime_len : 256);
-  header[sizeof(header) - 1] = '\0';
+  unsigned char *tmp;
 
-  /* Check for mandatory Content-Type field */
-  if (!strstr(header, MIME_CONTENT_TYPE))
-    return FALSE;
-  
   /* Get the pointer to the data area in the object */
   for (i = 0; i < mime_len; i++) {
-    if (mime_len >= i + 4 &&
-       mime[i    ] == '\r' && mime[i + 1] == '\n' &&
-       mime[i + 2] == '\r' && mime[i + 3] == '\n')
+    if ((mime_len >= i + 4 &&
+        mime[i    ] == '\r' && mime[i + 1] == '\n' &&
+        mime[i + 2] == '\r' && mime[i + 3] == '\n') ||
+       (mime_len >= i + 2 &&
+        mime[i    ] == '\n' && mime[i + 1] == '\n'))
       break;
   }
   if (i >= mime_len)
     return FALSE;
 
   if (mime_data_ptr)
-    *mime_data_ptr = (unsigned char *)mime + i + 4;
+    *mime_data_ptr = (unsigned char *)mime + i +
+           (mime[i] == '\n' ? 2 : 4);
   if (mime_data_len)
-    *mime_data_len = mime_len - ((mime + i + 4) - mime);
-  
+    *mime_data_len = mime_len - (i + (mime[i] == '\n' ? 2 : 4));
+
+  /* Check for mandatory Content-Type field */
+  tmp = strstr(mime, MIME_CONTENT_TYPE);
+  if (!tmp || (tmp - mime) >= i)
+    return FALSE;
+
   /* Get MIME version, Content-Type and Transfer Encoding fields */
-  MIME_GET_FIELD(header, mime, mime_len,
+  MIME_GET_FIELD(mime, mime_len,
                 MIME_VERSION, MIME_VERSION_LEN,
                 version, version_size);
-  MIME_GET_FIELD(header, mime, mime_len,
+  MIME_GET_FIELD(mime, mime_len,
                 MIME_CONTENT_TYPE, MIME_CONTENT_TYPE_LEN,
                 content_type, content_type_size);
-  MIME_GET_FIELD(header, mime, mime_len,
+  MIME_GET_FIELD(mime, mime_len,
                 MIME_TRANSFER_ENCODING, MIME_TRANSFER_ENCODING_LEN,
                 transfer_encoding, transfer_encoding_size);
 
@@ -617,3 +273,123 @@ char *silc_strncat(char *dest, SilcUInt32 dest_size,
 
   return dest;
 }
+
+/* Checks that the 'identifier' string is valid identifier string
+   and does not contain any unassigned or prohibited character.  This
+   function is used to check for valid nicknames, channel names,
+   server names, usernames, hostnames, service names, algorithm names,
+   other security property names, and SILC Public Key name. */
+
+unsigned char *silc_identifier_check(const unsigned char *identifier,
+                                    SilcUInt32 identifier_len,
+                                    SilcStringEncoding identifier_encoding,
+                                    SilcUInt32 max_allowed_length,
+                                    SilcUInt32 *out_len)
+{
+  unsigned char *utf8s;
+  SilcUInt32 utf8s_len;
+  SilcStringprepStatus status;
+
+  if (!identifier || !identifier_len)
+    return NULL;
+
+  if (max_allowed_length && identifier_len > max_allowed_length)
+    return NULL;
+
+  status = silc_stringprep(identifier, identifier_len,
+                          identifier_encoding, SILC_IDENTIFIER_PREP, 0,
+                          &utf8s, &utf8s_len, SILC_STRING_UTF8);
+  if (status != SILC_STRINGPREP_OK) {
+    SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+    return NULL;
+  }
+
+  if (out_len)
+    *out_len = utf8s_len;
+
+  return utf8s;
+}
+
+/* Same as above but does not allocate memory, just checks the
+   validity of the string. */
+
+bool silc_identifier_verify(const unsigned char *identifier,
+                           SilcUInt32 identifier_len,
+                           SilcStringEncoding identifier_encoding,
+                           SilcUInt32 max_allowed_length)
+{
+  SilcStringprepStatus status;
+
+  if (!identifier || !identifier_len)
+    return FALSE;
+
+  if (max_allowed_length && identifier_len > max_allowed_length)
+    return FALSE;
+
+  status = silc_stringprep(identifier, identifier_len,
+                          identifier_encoding, SILC_IDENTIFIER_PREP, 0,
+                          NULL, NULL, SILC_STRING_UTF8);
+  if (status != SILC_STRINGPREP_OK) {
+    SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+unsigned char *silc_channel_name_check(const unsigned char *identifier,
+                                      SilcUInt32 identifier_len,
+                                      SilcStringEncoding identifier_encoding,
+                                      SilcUInt32 max_allowed_length,
+                                      SilcUInt32 *out_len)
+{
+  unsigned char *utf8s;
+  SilcUInt32 utf8s_len;
+  SilcStringprepStatus status;
+
+  if (!identifier || !identifier_len)
+    return NULL;
+
+  if (max_allowed_length && identifier_len > max_allowed_length)
+    return NULL;
+
+  status = silc_stringprep(identifier, identifier_len,
+                          identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
+                          &utf8s, &utf8s_len, SILC_STRING_UTF8);
+  if (status != SILC_STRINGPREP_OK) {
+    SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+    return NULL;
+  }
+
+  if (out_len)
+    *out_len = utf8s_len;
+
+  return utf8s;
+}
+
+/* Same as above but does not allocate memory, just checks the
+   validity of the string. */
+
+bool silc_channel_name_verify(const unsigned char *identifier,
+                             SilcUInt32 identifier_len,
+                             SilcStringEncoding identifier_encoding,
+                             SilcUInt32 max_allowed_length)
+{
+  SilcStringprepStatus status;
+
+  if (!identifier || !identifier_len)
+    return FALSE;
+
+  if (max_allowed_length && identifier_len > max_allowed_length)
+    return FALSE;
+
+  status = silc_stringprep(identifier, identifier_len,
+                          identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0,
+                          NULL, NULL, SILC_STRING_UTF8);
+  if (status != SILC_STRINGPREP_OK) {
+    SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+    return FALSE;
+  }
+
+  return TRUE;
+}
index 35e9781227bbbf520bceafcf5318ba32ab9d476e..43ad42fbd498ee5502fbdfc91e97365fc3c3fad3 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcstrutil.h 
+  silcstrutil.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 - 2003 Pekka Riikonen
+  Copyright (C) 2002 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #ifndef SILCSTRUTIL_H
 #define SILCSTRUTIL_H
 
+/****d* silcutil/SilcStrUtilAPI/SilcStringEncoding
+ *
+ * NAME
+ *
+ *    typedef enum { ... } SilcStringEncoding;
+ *
+ * DESCRIPTION
+ *
+ *    String encoding definitions used with various string manipulation
+ *    routines.  By default, applications are suggested to use
+ *    SILC_STRING_LOCALE since it encodes and decodes correctly according
+ *    to local system language and character set (locale).
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_STRING_ASCII         = 0,  /* Any 8 bit ASCII encoding (default) */
+  SILC_STRING_ASCII_ESC     = 1,  /* 7 bit ASCII (>0x7f escaped) */
+  SILC_STRING_BMP           = 2,  /* 16 bit, UCS-2, BMP, ISO/IEC 10646 */
+  SILC_STRING_BMP_LSB       = 3,  /* BMP, least significant byte first */
+  SILC_STRING_UNIVERSAL     = 4,  /* 32 bit, UCS-4, Universal, ISO/IEC 10646 */
+  SILC_STRING_UNIVERSAL_LSB = 5,  /* Universal, least significant byte first */
+  SILC_STRING_LOCALE        = 6,  /* A locale specific conversion on
+                                    those platforms that support iconv().
+                                    Fallback is SILC_STRING_ASCII. */
+  SILC_STRING_UTF8          = 7,  /* UTF-8 encoding */
+  SILC_STRING_PRINTABLE     = 8,  /* Printable ASCII (no escaping) */
+  SILC_STRING_VISIBLE       = 9,  /* Visible ASCII string */
+  SILC_STRING_TELETEX       = 10, /* Teletex ASCII string */
+  SILC_STRING_NUMERICAL     = 11, /* Numerical ASCII string (digits) */
+  SILC_STRING_LDAP_DN       = 12, /* Strings for LDAP DNs, RFC 2253 */
+  SILC_STRING_UTF8_ESCAPE   = 12, /* Escaped UTF-8 as defined in RFC 2253 */
+
+  SILC_STRING_LANGUAGE      = 6,  /* _Deprecated_, use SILC_STRING_LOCALE. */
+} SilcStringEncoding;
+/***/
+
 /****f* silcutil/SilcStrUtilAPI/silc_pem_encode
  *
  * SYNOPSIS
@@ -74,180 +111,208 @@ char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len);
 unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len,
                               SilcUInt32 *ret_len);
 
-/****d* silcutil/SilcStrUtilAPI/SilcStringEncoding
- *
- * NAME
- * 
- *    typedef enum { ... } SilcStringEncoding;
- *
- * DESCRIPTION
- *
- *    String encoding definitions used with the UTF-8 encoding and
- *    decoding functions.  By default, systems should use SILC_STRING_LANGUAGE
- *    since it encodes and decodes correctly according to local system
- *    language and character set.
- *
- * SOURCE
- */
-typedef enum {
-  SILC_STRING_ASCII         = 0,  /* Any 8 bit ASCII encoding (default) */
-  SILC_STRING_ASCII_ESC     = 1,  /* 7 bit ASCII (>0x7f escaped) */
-  SILC_STRING_BMP           = 2,  /* 16 bit, UCS-2, BMP, ISO/IEC 10646 */
-  SILC_STRING_BMP_LSB       = 3,  /* BMP, least significant byte first */
-  SILC_STRING_UNIVERSAL     = 4,  /* 32 bit, UCS-4, Universal, ISO/IEC 10646 */
-  SILC_STRING_UNIVERSAL_LSB = 5,  /* Universal, least significant byte first */
-  SILC_STRING_LANGUAGE      = 6,  /* Language and charset specific conversion
-                                    on those platforms that support iconv().
-                                    Fallback is SILC_STRING_ASCII. */
-} SilcStringEncoding;
-/***/
-
-/****f* silcutil/SilcStrUtilAPI/silc_utf8_encode
+/****f* silcutil/SilcStrUtilAPI/silc_mime_parse
  *
  * SYNOPSIS
  *
- *    SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
- *                                SilcStringEncoding bin_encoding,
- *                                unsigned char *utf8, SilcUInt32 utf8_size);
+ *    bool
+ *    silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
+ *                    char *version, SilcUInt32 version_size,
+ *                    char *content_type, SilcUInt32 content_type_size,
+ *                    char *transfer_encoding,
+ *                    SilcUInt32 transfer_encoding_size,
+ *                    unsigned char **mime_data_ptr,
+ *                    SilcUInt32 *mime_data_len);
  *
  * DESCRIPTION
  *
- *    Encodes the string `bin' of which encoding is `bin_encoding' to the
- *    UTF-8 encoding into the buffer `utf8' which is of size of `utf8_size'.
- *    Returns the length of the UTF-8 encoded string, or zero (0) on error.
- *    By default `bin_encoding' is ASCII, and the caller needs to know the
- *    encoding of the input string if it is anything else.
+ *    Parses MIME header indicated by `mime' data block of length of
+ *    `mime_len'.  Returns TRUE if the `mime' is valid MIME object.
+ *    Parses from the MIME header the MIME Version (if present) and
+ *    copies it to the `version' pointer if provided, content type
+ *    indicating the data in the MIME object and copies it to the
+ *    `content_type' if provided, and the tranfer encoding (if present)
+ *    indicating the encoding of the data and copies it to the
+ *    `content_transfer_encoding' if provided.
+ *
+ *    The pointer to the actual data in the MIME object is saved into
+ *    `mime_data_ptr'.  The pointer is a location in the `mime' and it
+ *    does not allocate or copy anything, ie. the `mime_data_ptr' is a
+ *    pointer to the `mime'.  The `mime_data_len' indicates the length of
+ *    the data without the MIME header.  The caller is responsible of
+ *    NULL terminating the buffers it provides.
  *
  ***/
-SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
-                           SilcStringEncoding bin_encoding,
-                           unsigned char *utf8, SilcUInt32 utf8_size);
+bool
+silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
+                char *version, SilcUInt32 version_size,
+                char *content_type, SilcUInt32 content_type_size,
+                char *transfer_encoding, SilcUInt32 transfer_encoding_size,
+                unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len);
 
-/****f* silcutil/SilcStrUtilAPI/silc_utf8_decode
+/****f* silcutil/SilcStrUtilAPI/silc_strncat
  *
  * SYNOPSIS
  *
- *    SilcUInt32 silc_utf8_decode(const unsigned char *utf8, 
- *                                SilcUInt32 utf8_len,
- *                                SilcStringEncoding bin_encoding,
- *                                unsigned char *bin, SilcUInt32 bin_size);
+ *    char *silc_strncat(char *dest, SilcUInt32 dest_size,
+ *                       const char *src, SilcUInt32 src_len);
  *
  * DESCRIPTION
  *
- *    Decodes UTF-8 encoded string `utf8' to string of which encoding is
- *    to be `bin_encoding', into the `bin' buffer of size of `bin_size'.
- *    Returns the length of the decoded buffer, or zero (0) on error.
- *    By default `bin_encoding' is ASCII, and the caller needs to know to
- *    which encoding the output string is to be encoded if ASCII is not
- *    desired. 
+ *    Concatenates the `src' into `dest'.  If `src_len' is more than the
+ *    size of the `dest' (minus NULL at the end) the `src' will be
+ *    truncated to fit.
  *
  ***/
-SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
-                           SilcStringEncoding bin_encoding,
-                           unsigned char *bin, SilcUInt32 bin_size);
+char *silc_strncat(char *dest, SilcUInt32 dest_size,
+                  const char *src, SilcUInt32 src_len);
 
-/****f* silcutil/SilcStrUtilAPI/silc_utf8_encoded_len
+/****f* silcutil/SilcStrUtilAPI/silc_identifier_check
  *
  * SYNOPSIS
  *
- *    SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, 
- *                                     SilcUInt32 bin_len,
- *                                     SilcStringEncoding bin_encoding);
+ *    unsigned char *
+ *    silc_identifier_check(const unsigned char *identifier,
+ *                          SilcUInt32 identifier_len,
+ *                          SilcStringEncoding identifier_encoding,
+ *                          SilcUInt32 max_allowed_length,
+ *                          SilcUInt32 *out_len);
  *
  * DESCRIPTION
  *
- *    Returns the length of UTF-8 encoded string if the `bin' of
- *    encoding of `bin_encoding' is encoded with silc_utf8_encode.
+ *    Checks that the 'identifier' string is valid identifier string
+ *    and does not contain any unassigned or prohibited character.  This
+ *    function is used to check for valid nicknames, server names, 
+ *    usernames, hostnames, service names, algorithm names, other security 
+ *    property names, and SILC Public Key name.
  *
- ***/
-SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len,
-                                SilcStringEncoding bin_encoding);
-
-/****f* silcutil/SilcStrUtilAPI/silc_utf8_decoded_len
- *
- * SYNOPSIS
+ *    If the 'max_allowed_length' is non-zero the identifier cannot be
+ *    longer than that, and NULL is returned if it is.  If zero (0), no
+ *    length limit exist.  For nicknames the max length must be 128 bytes.
+ *    Other identifiers has no default limit, but application may choose 
+*     one anyway.
  *
- *    SilcUInt32 silc_utf8_decoded_len(const unsigned char *bin, 
- *                                     SilcUInt32 bin_len,
- *                                     SilcStringEncoding bin_encoding);
+ *    Returns the validated string, that the caller must free.  Returns
+ *    NULL if the identifier string is not valid or contain unassigned or
+ *    prohibited characters.  Such identifier strings must not be used
+ *    SILC protocol.  The returned string is always in UTF-8 encoding.
+ *    The length of the returned string is in 'out_len'.
  *
- * DESCRIPTION
+ * NOTES
  *
- *    Returns the length of decoded string if the `bin' of encoding of
- *    `bin_encoding' is decoded with silc_utf8_decode. 
+ *    In addition of validating the identifier string, this function
+ *    may map characters to other characters or remove characters from the
+ *    original string.  This is done as defined in the SILC protocol.  Error
+ *    is returned only if the string contains unassigned or prohibited
+ *    characters.  The original 'identifier' is not modified at any point.
  *
  ***/
-SilcUInt32 silc_utf8_decoded_len(const unsigned char *bin, SilcUInt32 bin_len,
-                                SilcStringEncoding bin_encoding);
+unsigned char *silc_identifier_check(const unsigned char *identifier,
+                                    SilcUInt32 identifier_len,
+                                    SilcStringEncoding identifier_encoding,
+                                    SilcUInt32 max_allowed_length,
+                                    SilcUInt32 *out_len);
 
-/****f* silcutil/SilcStrUtilAPI/silc_utf8_valid
+/****f* silcutil/SilcStrUtilAPI/silc_identifier_verify
  *
  * SYNOPSIS
  *
- *    bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len);
+ *    bool
+ *    silc_identifier_check(const unsigned char *identifier,
+ *                          SilcUInt32 identifier_len,
+ *                          SilcStringEncoding identifier_encoding,
+ *                          SilcUInt32 max_allowed_length);
  *
  * DESCRIPTION
  *
- *    Returns TRUE if the `utf8' string of length of `utf8_len' is valid
- *    UTF-8 encoded string, FALSE if it is not UTF-8 encoded string.
+ *    Checks that the 'identifier' string is valid identifier string
+ *    and does not contain any unassigned or prohibited character.  This
+ *    function is used to check for valid nicknames, server names, 
+ *    usernames, hostnames, service names, algorithm names, other security 
+ *    property names, and SILC Public Key name.
+ *
+ *    If the 'max_allowed_length' is non-zero the identifier cannot be
+ *    longer than that, and NULL is returned if it is.  If zero (0), no
+ *    length limit exist.  For nicknames the max length must be 128 bytes.
+ *    Other identifiers has no default limit, but application may choose 
+ *    one anyway.
+ *
+ *    Returns TRUE if the string is valid and FALSE if it is prohibited.
  *
  ***/
-bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len);
+bool silc_identifier_verify(const unsigned char *identifier,
+                           SilcUInt32 identifier_len,
+                           SilcStringEncoding identifier_encoding,
+                           SilcUInt32 max_allowed_length);
 
-/****f* silcutil/SilcStrUtilAPI/silc_mime_parse
+/****f* silcutil/SilcStrUtilAPI/silc_channel_name_check
  *
  * SYNOPSIS
  *
- *    bool
- *    silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
- *                    char *version, SilcUInt32 version_size,
- *                    char *content_type, SilcUInt32 content_type_size,
- *                    char *transfer_encoding,
- *                    SilcUInt32 transfer_encoding_size,
- *                    unsigned char **mime_data_ptr,
- *                    SilcUInt32 *mime_data_len);
+ *    unsigned char *
+ *    silc_channel_name_check(const unsigned char *identifier,
+ *                            SilcUInt32 identifier_len,
+ *                            SilcStringEncoding identifier_encoding,
+ *                            SilcUInt32 max_allowed_length,
+ *                            SilcUInt32 *out_len);
  *
  * DESCRIPTION
  *
- *    Parses MIME header indicated by `mime' data block of length of
- *    `mime_len'.  Returns TRUE if the `mime' is valid MIME object.
- *    Parses from the MIME header the MIME Version (if present) and
- *    copies it to the `version' pointer if provided, content type
- *    indicating the data in the MIME object and copies it to the
- *    `content_type' if provided, and the tranfer encoding (if present)
- *    indicating the encoding of the data and copies it to the
- *    `content_transfer_encoding' if provided.
+ *    Checks that the 'identifier' string is valid channel name string
+ *    and does not contain any unassigned or prohibited character.
  *
- *    The pointer to the actual data in the MIME object is saved into 
- *    `mime_data_ptr'.  The pointer is a location in the `mime' and it 
- *    does not allocate or copy anything, ie. the `mime_data_ptr' is a 
- *    pointer to the `mime'.  The `mime_data_len' indicates the length of 
- *    the data without the MIME header.  The caller is responsible of
- *    NULL terminating the buffers it provides.
+ *    If the 'max_allowed_length' is non-zero the identifier cannot be
+ *    longer than that, and NULL is returned if it is.  If zero (0), no
+ *    length limit exist.  For channel names the max length must be 256
+ *    bytes.
+ *
+ *    Returns the validated string, that the caller must free.  Returns
+ *    NULL if the identifier string is not valid or contain unassigned or
+ *    prohibited characters.  Such identifier strings must not be used
+ *    SILC protocol.  The returned string is always in UTF-8 encoding.
+ *    The length of the returned string is in 'out_len'.
+ *
+ * NOTES
+ *
+ *    In addition of validating the channel name string, this function
+ *    may map characters to other characters or remove characters from the
+ *    original string.  This is done as defined in the SILC protocol.  Error
+ *    is returned only if the string contains unassigned or prohibited
+ *    characters.  The original 'identifier' is not modified at any point.
  *
  ***/
-bool
-silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
-                char *version, SilcUInt32 version_size,
-                char *content_type, SilcUInt32 content_type_size,
-                char *transfer_encoding, SilcUInt32 transfer_encoding_size,
-                unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len);
+unsigned char *silc_channel_name_check(const unsigned char *identifier,
+                                      SilcUInt32 identifier_len,
+                                      SilcStringEncoding identifier_encoding,
+                                      SilcUInt32 max_allowed_length,
+                                      SilcUInt32 *out_len);
 
-/****f* silcutil/SilcStrUtilAPI/silc_strncat
+/****f* silcutil/SilcStrUtilAPI/silc_channel_name_verify
  *
  * SYNOPSIS
  *
- *    char *silc_strncat(char *dest, SilcUInt32 dest_size,
- *                       const char *src, SilcUInt32 src_len);
+ *    bool
+ *    silc_channel_name_check(const unsigned char *identifier,
+ *                            SilcUInt32 identifier_len,
+ *                            SilcStringEncoding identifier_encoding,
+ *                            SilcUInt32 max_allowed_length);
  *
  * DESCRIPTION
  *
- *    Concatenates the `src' into `dest'.  If `src_len' is more than the
- *    size of the `dest' (minus NULL at the end) the `src' will be
- *    truncated to fit.
+ *    Checks that the 'identifier' string is valid channel name string
+ *    and does not contain any unassigned or prohibited character.
+ *
+ *    If the 'max_allowed_length' is non-zero the identifier cannot be
+ *    longer than that, and NULL is returned if it is.  If zero (0), no
+ *    length limit exist.  For channel names the max length must be 256
+ *    bytes.
+ *
+ *    Returns TRUE if the string is valid and FALSE if it is prohibited.
  *
  ***/
-char *silc_strncat(char *dest, SilcUInt32 dest_size,
-                  const char *src, SilcUInt32 src_len);
+bool silc_channel_name_verify(const unsigned char *identifier,
+                             SilcUInt32 identifier_len,
+                             SilcStringEncoding identifier_encoding,
+                             SilcUInt32 max_allowed_length);
 
 #endif /* SILCSTRUTIL_H */
index c763f8fa3b6be5fa1b6f613bbc0a926cdd6d2354..e98bc8c82bdf47f18a85b4f0a4f7a1d0a9df2897 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silctypes.h 
+  silctypes.h
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
  *
  * SOURCE
  */
+#ifdef SILC_MACOSX
+#define bool _Bool
+#endif
+
 #ifndef __cplusplus
 #ifndef bool
 #define bool unsigned char
@@ -491,4 +495,91 @@ do {                                               \
                (((SilcUInt32)(l) & (SilcUInt32)0xFF000000UL) >> 24))
 /***/
 
+/****d* silcutil/SILCTypes/SILC_PTR_TO_32
+ *
+ * NAME
+ *
+ *    #define SILC_PTR_TO_32 ...
+ *
+ * DESCRIPTION
+ *
+ *    Type casts a pointer's value into a 32-bit integer.  Use this to
+ *    avoid compiler warnings when type casting pointers to integers
+ *    of different size.
+ *
+ * SOURCE
+ */
+#if SILC_SIZEOF_VOID_P < 8
+#define SILC_PTR_TO_32(_ptr__) ((SilcUInt32)(_ptr__))
+#else
+#define SILC_PTR_TO_32(_ptr__)                                                 \
+  ((SilcUInt32)((SilcUInt64)(_ptr__) & (SilcUInt32)0xFFFFFFFFUL))
+#endif
+/***/
+
+/****d* silcutil/SILCTypes/SILC_PTR_TO_64
+ *
+ * NAME
+ *
+ *    #define SILC_PTR_TO_64 ...
+ *
+ * DESCRIPTION
+ *
+ *    Type casts a pointer's value into a 64-bit integer.  Use this to
+ *    avoid compiler warnings when type casting pointers to integers
+ *    of different size.
+ *
+ * SOURCE
+ */
+#if SILC_SIZEOF_VOID_P < 8
+#define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt32)(_ptr__)))
+#else
+#define SILC_PTR_TO_64(_ptr__)                                                 \
+  ((SilcUInt64)((SilcUInt64)(_ptr__) & (SilcUInt32)0xFFFFFFFFUL))
+#endif
+/***/
+
+/****d* silcutil/SILCTypes/SILC_32_TO_PTR
+ *
+ * NAME
+ *
+ *    #define SILC_PTR_TO_32 ...
+ *
+ * DESCRIPTION
+ *
+ *    Type casts a 32-bit integer value into a pointer.  Use this to
+ *    avoid compiler warnings when type casting integers to pointers of
+ *    different size.
+ *
+ * SOURCE
+ */
+#if SILC_SIZEOF_VOID_P < 8
+#define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt32)(_ival__)))
+#else
+#define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
+#endif
+/***/
+
+/****d* silcutil/SILCTypes/SILC_64_TO_PTR
+ *
+ * NAME
+ *
+ *    #define SILC_PTR_TO_64 ...
+ *
+ * DESCRIPTION
+ *
+ *    Type casts a 64-bit integer value into a pointer.  Use this to
+ *    avoid compiler warnings when type casting integers to pointers of
+ *    different size.
+ *
+ * SOURCE
+ */
+#if SILC_SIZEOF_VOID_P < 8
+#define SILC_64_TO_PTR(_ival__)                                                \
+  ((void *)((SilcUInt32)((SilcUInt64)(_ival__) & (SilcUInt32)0xFFFFFFFFUL)))
+#else
+#define SILC_64_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
+#endif
+/***/
+
 #endif /* SILCTYPES_H */
diff --git a/lib/silcutil/silcutf8.c b/lib/silcutil/silcutf8.c
new file mode 100644 (file)
index 0000000..af6cac3
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+
+  silcutf8.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 - 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+#include "silcincludes.h"
+#include "silcutf8.h"
+
+/* Encodes the string `bin' of which encoding is `bin_encoding' to the
+   UTF-8 encoding into the buffer `utf8' which is of size of `utf8_size'.
+   Returns the length of the UTF-8 encoded string, or zero (0) on error.
+   By default `bin_encoding' is ASCII, and the caller needs to know the
+   encoding of the input string if it is anything else. */
+
+SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
+                           SilcStringEncoding bin_encoding,
+                           unsigned char *utf8, SilcUInt32 utf8_size)
+{
+  SilcUInt32 enclen = 0, i, charval = 0;
+
+  if (!bin || !bin_len)
+    return 0;
+
+  if (bin_encoding == SILC_STRING_UTF8) {
+    if (!silc_utf8_valid(bin, bin_len))
+      return 0;
+    if (!utf8)
+      return bin_len;
+    if (bin_len > utf8_size)
+      return 0;
+    memcpy(utf8, bin, bin_len);
+    return bin_len;
+  }
+
+  /* The SILC_STRING_LDAP_DN is alredy UTF-8 but it may be escaped.  We
+     remove the escaping and we're done. */
+  if (bin_encoding == SILC_STRING_LDAP_DN ||
+      bin_encoding == SILC_STRING_UTF8_ESCAPE) {
+    unsigned char cv;
+
+    for (i = 0; i < bin_len; i++) {
+      if (bin[i] == '\\') {
+       if (i + 1 >= bin_len)
+         return 0;
+
+       /* If escaped character is any of the following no processing is
+          needed, otherwise it is a hex value and we need to read it. */
+       cv = bin[i + 1];
+       if (cv != ',' && cv != '+' && cv != '"' && cv != '\\' && cv != '<' &&
+           cv != '>' && cv != ';' && cv != ' ' && cv != '#') {
+         unsigned int hexval;
+         if (i + 2 >= bin_len)
+           return 0;
+         if (sscanf(&bin[i + 1], "%02X", &hexval) != 1)
+           return 0;
+         if (utf8) {
+           if (enclen + 1 > utf8_size)
+             return 0;
+           utf8[enclen] = (unsigned char)hexval;
+         }
+
+         i += 2;
+         enclen++;
+         continue;
+       }
+       i++;
+      }
+
+      if (utf8) {
+       if (enclen + 1 > utf8_size)
+         return 0;
+       utf8[enclen] = bin[i];
+      }
+      enclen++;
+    }
+
+    return enclen;
+  }
+
+  if (bin_encoding == SILC_STRING_LOCALE) {
+#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
+    char *fromconv, *icp, *ocp;
+    iconv_t icd;
+    size_t inlen, outlen;
+
+    setlocale(LC_CTYPE, "");
+    fromconv = nl_langinfo(CODESET);
+    if (fromconv && strlen(fromconv)) {
+      icd = iconv_open("UTF-8", fromconv);
+      icp = (char *)bin;
+      ocp = (char *)utf8;
+      inlen = bin_len;
+      outlen = utf8_size;
+      if (icp && ocp && icd != (iconv_t)-1) {
+       if (iconv(icd, &icp, &inlen, &ocp, &outlen) != -1) {
+         utf8_size -= outlen;
+         iconv_close(icd);
+         return utf8_size;
+       }
+      }
+      if (icd != (iconv_t)-1)
+       iconv_close(icd);
+    }
+#endif
+
+    /* Fallback to 8-bit ASCII */
+    bin_encoding = SILC_STRING_ASCII;
+  }
+
+  for (i = 0; i < bin_len; i++) {
+    switch (bin_encoding) {
+    case SILC_STRING_ASCII:
+    case SILC_STRING_TELETEX:
+      charval = bin[i];
+      break;
+    case SILC_STRING_ASCII_ESC:
+      SILC_NOT_IMPLEMENTED("SILC_STRING_ASCII_ESC");
+      return 0;
+      break;
+    case SILC_STRING_BMP:
+      if (i + 1 >= bin_len)
+       return 0;
+      SILC_GET16_MSB(charval, bin + i);
+      i += 1;
+      break;
+    case SILC_STRING_BMP_LSB:
+      if (i + 1 >= bin_len)
+       return 0;
+      SILC_GET16_LSB(charval, bin + i);
+      i += 1;
+      break;
+    case SILC_STRING_UNIVERSAL:
+      if (i + 3 >= bin_len)
+       return 0;
+      SILC_GET32_MSB(charval, bin + i);
+      i += 3;
+      break;
+    case SILC_STRING_UNIVERSAL_LSB:
+      if (i + 3 >= bin_len)
+       return 0;
+      SILC_GET32_LSB(charval, bin + i);
+      i += 3;
+      break;
+    case SILC_STRING_PRINTABLE:
+    case SILC_STRING_VISIBLE:
+      if (!isprint(bin[i]))
+       return 0;
+      charval = bin[i];
+      break;
+    case SILC_STRING_NUMERICAL:
+      if (bin[i] != 0x20 && !isdigit(bin[i]))
+       return 0;
+      charval = bin[i];
+      break;
+    default:
+      return 0;
+      break;
+    }
+
+    if (charval < 0x80) {
+      if (utf8) {
+       if (enclen > utf8_size)
+         return 0;
+
+       utf8[enclen] = (unsigned char)charval;
+      }
+      enclen++;
+    } else if (charval < 0x800) {
+      if (utf8) {
+       if (enclen + 2 > utf8_size)
+         return 0;
+
+       utf8[enclen    ] = (unsigned char )(((charval >> 6)  & 0x1f) | 0xc0);
+       utf8[enclen + 1] = (unsigned char )((charval & 0x3f) | 0x80);
+      }
+      enclen += 2;
+    } else if (charval < 0x10000) {
+      if (utf8) {
+       if (enclen + 3 > utf8_size)
+         return 0;
+
+       utf8[enclen    ] = (unsigned char )(((charval >> 12) & 0xf)  | 0xe0);
+       utf8[enclen + 1] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
+       utf8[enclen + 2] = (unsigned char )((charval & 0x3f) | 0x80);
+      }
+      enclen += 3;
+    } else if (charval < 0x200000) {
+      if (utf8) {
+       if (enclen + 4 > utf8_size)
+         return 0;
+
+       utf8[enclen    ] = (unsigned char )(((charval >> 18) & 0x7)  | 0xf0);
+       utf8[enclen + 1] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
+       utf8[enclen + 2] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
+       utf8[enclen + 3] = (unsigned char )((charval & 0x3f) | 0x80);
+      }
+      enclen += 4;
+    } else if (charval < 0x4000000) {
+      if (utf8) {
+       if (enclen + 5 > utf8_size)
+         return 0;
+
+       utf8[enclen    ] = (unsigned char )(((charval >> 24) & 0x3)  | 0xf8);
+       utf8[enclen + 1] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80);
+       utf8[enclen + 2] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
+       utf8[enclen + 3] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
+       utf8[enclen + 4] = (unsigned char )((charval & 0x3f) | 0x80);
+      }
+      enclen += 5;
+    } else {
+      if (utf8) {
+       if (enclen + 6 > utf8_size)
+         return 0;
+
+       utf8[enclen    ] = (unsigned char )(((charval >> 30) & 0x1)  | 0xfc);
+       utf8[enclen + 1] = (unsigned char )(((charval >> 24) & 0x3f) | 0x80);
+       utf8[enclen + 2] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80);
+       utf8[enclen + 3] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
+       utf8[enclen + 4] = (unsigned char )(((charval >> 6)  & 0x3f) | 0x80);
+       utf8[enclen + 5] = (unsigned char )((charval & 0x3f) | 0x80);
+      }
+      enclen += 6;
+    }
+  }
+
+  return enclen;
+}
+
+/* Decodes UTF-8 encoded string `utf8' to string of which encoding is
+   to be `bin_encoding', into the `bin' buffer of size of `bin_size'.
+   Returns the length of the decoded buffer, or zero (0) on error.
+   By default `bin_encoding' is ASCII, and the caller needs to know to
+   which encoding the output string is to be encoded if ASCII is not
+   desired. */
+
+SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
+                           SilcStringEncoding bin_encoding,
+                           unsigned char *bin, SilcUInt32 bin_size)
+{
+  SilcUInt32 enclen = 0, i, charval, bytes;
+
+  if (!utf8 || !utf8_len)
+    return 0;
+
+  if (bin_encoding == SILC_STRING_UTF8) {
+    if (!silc_utf8_valid(utf8, utf8_len) ||
+       utf8_len > bin_size)
+      return 0;
+    memcpy(bin, utf8, utf8_len);
+    return utf8_len;
+  }
+
+  if (bin_encoding == SILC_STRING_LOCALE) {
+#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
+    char *toconv, *icp, *ocp;
+    iconv_t icd;
+    size_t inlen, outlen;
+
+    setlocale(LC_CTYPE, "");
+    toconv = nl_langinfo(CODESET);
+    if (toconv && strlen(toconv)) {
+      icd = iconv_open(toconv, "UTF-8");
+      icp = (char *)utf8;
+      ocp = (char *)bin;
+      inlen = utf8_len;
+      outlen = bin_size;
+      if (icp && ocp && icd != (iconv_t)-1) {
+       if (iconv(icd, &icp, &inlen, &ocp, &outlen) != -1) {
+         bin_size -= outlen;
+         iconv_close(icd);
+         return bin_size;
+       }
+      }
+      if (icd != (iconv_t)-1)
+       iconv_close(icd);
+    }
+#endif
+
+    /* Fallback to 8-bit ASCII */
+    bin_encoding = SILC_STRING_ASCII;
+  }
+
+  for (i = 0; i < utf8_len; i++) {
+    if ((utf8[i] & 0x80) == 0x00) {
+      charval = utf8[i] & 0x7f;
+      bytes = 1;
+    } else if ((utf8[i] & 0xe0) == 0xc0) {
+      if (i + 1 >= utf8_len)
+       return 0;
+
+      if ((utf8[i + 1] & 0xc0) != 0x80)
+        return 0;
+
+      charval = (utf8[i++] & 0x1f) << 6;
+      charval |= utf8[i] & 0x3f;
+      if (charval < 0x80)
+        return 0;
+      bytes = 2;
+    } else if ((utf8[i] & 0xf0) == 0xe0) {
+      if (i + 2 >= utf8_len)
+       return 0;
+
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
+         ((utf8[i + 2] & 0xc0) != 0x80))
+        return 0;
+
+      /* Surrogates not allowed (D800-DFFF) */
+      if (utf8[i] == 0xed &&
+         utf8[i + 1] >= 0xa0 && utf8[i + 1] <= 0xbf &&
+         utf8[i + 2] >= 0x80 && utf8[i + 2] <= 0xbf)
+       return 0;
+
+      charval = (utf8[i++]  & 0xf)  << 12;
+      charval |= (utf8[i++] & 0x3f) << 6;
+      charval |= utf8[i] & 0x3f;
+      if (charval < 0x800)
+        return 0;
+      bytes = 3;
+    } else if ((utf8[i] & 0xf8) == 0xf0) {
+      if (i + 3 >= utf8_len)
+       return 0;
+
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
+         ((utf8[i + 2] & 0xc0) != 0x80) ||
+         ((utf8[i + 3] & 0xc0) != 0x80))
+        return 0;
+
+      charval = ((SilcUInt32)(utf8[i++] & 0x7)) << 18;
+      charval |= (utf8[i++] & 0x3f) << 12;
+      charval |= (utf8[i++] & 0x3f) << 6;
+      charval |= utf8[i] & 0x3f;
+      if (charval < 0x10000)
+        return 0;
+      bytes = 4;
+    } else if ((utf8[i] & 0xfc) == 0xf8) {
+      if (i + 4 >= utf8_len)
+       return 0;
+
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
+         ((utf8[i + 2] & 0xc0) != 0x80) ||
+         ((utf8[i + 3] & 0xc0) != 0x80) ||
+         ((utf8[i + 4] & 0xc0) != 0x80))
+        return 0;
+
+      charval = ((SilcUInt32)(utf8[i++]  & 0x3))  << 24;
+      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18;
+      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12;
+      charval |= (utf8[i++] & 0x3f) << 6;
+      charval |= utf8[i] & 0x3f;
+      if (charval < 0x200000)
+        return 0;
+      bytes = 5;
+    } else if ((utf8[i] & 0xfe) == 0xfc) {
+      if (i + 5 >= utf8_len)
+       return 0;
+
+      if (((utf8[i + 1] & 0xc0) != 0x80) ||
+         ((utf8[i + 2] & 0xc0) != 0x80) ||
+         ((utf8[i + 3] & 0xc0) != 0x80) ||
+         ((utf8[i + 4] & 0xc0) != 0x80) ||
+         ((utf8[i + 5] & 0xc0) != 0x80))
+        return 0;
+
+      charval = ((SilcUInt32)(utf8[i++]  & 0x1))  << 30;
+      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 24;
+      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18;
+      charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12;
+      charval |= (utf8[i++] & 0x3f) << 6;
+      charval |= utf8[i] & 0x3f;
+      if (charval < 0x4000000)
+        return 0;
+      bytes = 6;
+    } else {
+      return 0;
+    }
+
+    switch (bin_encoding) {
+    case SILC_STRING_ASCII:
+    case SILC_STRING_PRINTABLE:
+    case SILC_STRING_VISIBLE:
+    case SILC_STRING_TELETEX:
+    case SILC_STRING_NUMERICAL:
+      if (bin) {
+        if (enclen + 1 > bin_size)
+          return 0;
+
+        bin[enclen] = (unsigned char)charval;
+      }
+      enclen++;
+      break;
+    case SILC_STRING_ASCII_ESC:
+      SILC_NOT_IMPLEMENTED("SILC_STRING_ASCII_ESC");
+      return 0;
+      break;
+    case SILC_STRING_BMP:
+      if (bin) {
+        if (enclen + 2 > bin_size)
+          return 0;
+       SILC_PUT16_MSB(charval, bin + enclen);
+      }
+      enclen += 2;
+      break;
+    case SILC_STRING_BMP_LSB:
+      if (bin) {
+        if (enclen + 2 > bin_size)
+          return 0;
+       SILC_PUT16_LSB(charval, bin + enclen);
+      }
+      enclen += 2;
+      break;
+    case SILC_STRING_UNIVERSAL:
+      if (bin) {
+        if (enclen + 4 > bin_size)
+          return 0;
+       SILC_PUT32_MSB(charval, bin + enclen);
+      }
+      enclen += 4;
+      break;
+    case SILC_STRING_UNIVERSAL_LSB:
+      if (bin) {
+        if (enclen + 4 > bin_size)
+          return 0;
+       SILC_PUT32_LSB(charval, bin + enclen);
+      }
+      enclen += 4;
+      break;
+    case SILC_STRING_LDAP_DN:
+      {
+        int k;
+       unsigned char cv;
+
+       /* Non-printable UTF-8 characters will be escaped, printable will
+          be as is.  We take the bytes directly from the original data. */
+       for (k = 0; k < bytes; k++) {
+         cv = utf8[(i - (bytes - 1)) + k];
+
+         /* If string starts with space or # escape it */
+         if (!enclen && (cv == '#' || cv == ' ')) {
+           if (bin) {
+             if (enclen + 2 > bin_size)
+               return 0;
+             bin[enclen] = '\\';
+             bin[enclen + 1] = cv;
+           }
+           enclen += 2;
+           continue;
+         }
+
+         /* If string ends with space escape it */
+         if (i == utf8_len - 1 && cv == ' ') {
+           if (bin) {
+             if (enclen + 2 > bin_size)
+               return 0;
+             bin[enclen] = '\\';
+             bin[enclen + 1] = cv;
+           }
+           enclen += 2;
+           continue;
+         }
+
+         /* If character is any of following then escape */
+         if (cv == ',' || cv == '+' || cv == '"' || cv == '\\' || cv == '<' ||
+             cv == '>' || cv == ';') {
+           if (bin) {
+             if (enclen + 2 > bin_size)
+               return 0;
+             bin[enclen] = '\\';
+             bin[enclen + 1] = cv;
+           }
+           enclen += 2;
+           continue;
+         }
+
+         /* If character is not printable escape it with hex character */
+         if (!isprint((int)cv)) {
+           if (bin) {
+             if (enclen + 3 > bin_size)
+               return 0;
+             bin[enclen] = '\\';
+             snprintf(bin + enclen + 1, 3, "%02X", cv);
+           }
+           enclen += 3;
+           continue;
+         }
+
+         if (bin) {
+           if (enclen + 1 > bin_size)
+             return 0;
+           bin[enclen] = cv;
+         }
+         enclen++;
+       }
+      }
+      break;
+    default:
+      return 0;
+      break;
+    }
+  }
+
+  return enclen;
+}
+
+/* Returns the length of UTF-8 encoded string if the `bin' of
+   encoding of `bin_encoding' is encoded with silc_utf8_encode. */
+
+SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len,
+                                SilcStringEncoding bin_encoding)
+{
+  return silc_utf8_encode(bin, bin_len, bin_encoding, NULL, 0);
+}
+
+/* Returns the length of decoded string if the `bin' of encoding of
+   `bin_encoding' is decoded with silc_utf8_decode. */
+
+SilcUInt32 silc_utf8_decoded_len(const unsigned char *bin, SilcUInt32 bin_len,
+                                SilcStringEncoding bin_encoding)
+{
+  return silc_utf8_decode(bin, bin_len, bin_encoding, NULL, 0);
+}
+
+/* Returns TRUE if the `utf8' string of length of `utf8_len' is valid
+   UTF-8 encoded string, FALSE if it is not UTF-8 encoded string. */
+
+bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len)
+{
+  return silc_utf8_decode(utf8, utf8_len, 0, NULL, 0) != 0;
+}
+
+/* Pretty close strcasecmp */
+
+bool silc_utf8_strcasecmp(const char *s1, const char *s2)
+{
+  if (s1 == s2)
+    return TRUE;
+  if (strlen(s1) != strlen(s2))
+    return FALSE;
+
+  return silc_utf8_strncasecmp(s1, s2, strlen(s1));
+}
+
+/* Pretty close strcasecmp */
+
+bool silc_utf8_strncasecmp(const char *s1, const char *s2, SilcUInt32 n)
+{
+  unsigned char *s1u, *s2u;
+  SilcUInt32 s1u_len, s2u_len;
+  SilcStringprepStatus status;
+  bool ret;
+
+  if (s1 == s2)
+    return TRUE;
+
+  /* Casefold and normalize */
+  status = silc_stringprep(s1, strlen(s1), SILC_STRING_UTF8,
+                          SILC_IDENTIFIERC_PREP, 0, &s1u,
+                          &s1u_len, SILC_STRING_UTF8);
+  if (status != SILC_STRINGPREP_OK)
+    return FALSE;
+
+  /* Casefold and normalize */
+  status = silc_stringprep(s2, strlen(s2), SILC_STRING_UTF8,
+                          SILC_IDENTIFIERC_PREP, 0, &s2u,
+                          &s2u_len, SILC_STRING_UTF8);
+  if (status != SILC_STRINGPREP_OK)
+    return FALSE;
+
+  ret = !memcmp(s1u, s2u, n);
+
+  silc_free(s1u);
+  silc_free(s2u);
+
+  return ret;
+}
diff --git a/lib/silcutil/silcutf8.h b/lib/silcutil/silcutf8.h
new file mode 100644 (file)
index 0000000..ba09b4e
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+
+  silcutf8.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2004 - 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+/****h* silcutil/SILC UTF-8 Interface
+ *
+ * DESCRIPTION
+ *
+ * Interface for the UTF-8 Unicode encoding form.  These routines provides
+ * applications full UTF-8 and Unicode support.  It supports UTF-8 encoding
+ * to and decoding from myriad of other character encodings.
+ *
+ ***/
+
+#ifndef SILCUTF8_H
+#define SILCUTF8_H
+
+/****f* silcutil/SilcUTF8API/silc_utf8_encode
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
+ *                                SilcStringEncoding bin_encoding,
+ *                                unsigned char *utf8, SilcUInt32 utf8_size);
+ *
+ * DESCRIPTION
+ *
+ *    Encodes the string `bin' of which encoding is `bin_encoding' to the
+ *    UTF-8 encoding into the buffer `utf8' which is of size of `utf8_size'.
+ *    Returns the length of the UTF-8 encoded string, or zero (0) on error.
+ *    By default `bin_encoding' is ASCII, and the caller needs to know the
+ *    encoding of the input string if it is anything else.
+ *
+ ***/
+SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
+                           SilcStringEncoding bin_encoding,
+                           unsigned char *utf8, SilcUInt32 utf8_size);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_decode
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_utf8_decode(const unsigned char *utf8,
+ *                                SilcUInt32 utf8_len,
+ *                                SilcStringEncoding bin_encoding,
+ *                                unsigned char *bin, SilcUInt32 bin_size);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes UTF-8 encoded string `utf8' to string of which encoding is
+ *    to be `bin_encoding', into the `bin' buffer of size of `bin_size'.
+ *    Returns the length of the decoded buffer, or zero (0) on error.
+ *    By default `bin_encoding' is ASCII, and the caller needs to know to
+ *    which encoding the output string is to be encoded if ASCII is not
+ *    desired.
+ *
+ ***/
+SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
+                           SilcStringEncoding bin_encoding,
+                           unsigned char *bin, SilcUInt32 bin_size);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_encoded_len
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin,
+ *                                     SilcUInt32 bin_len,
+ *                                     SilcStringEncoding bin_encoding);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the length of UTF-8 encoded string if the `bin' of
+ *    encoding of `bin_encoding' is encoded with silc_utf8_encode.
+ *    Returns zero (0) on error.
+ *
+ ***/
+SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len,
+                                SilcStringEncoding bin_encoding);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_decoded_len
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_utf8_decoded_len(const unsigned char *bin,
+ *                                     SilcUInt32 bin_len,
+ *                                     SilcStringEncoding bin_encoding);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the length of decoded string if the `bin' of encoding of
+ *    `bin_encoding' is decoded with silc_utf8_decode.  Returns zero (0)
+ *    on error.
+ *
+ ***/
+SilcUInt32 silc_utf8_decoded_len(const unsigned char *bin, SilcUInt32 bin_len,
+                                SilcStringEncoding bin_encoding);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_valid
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len);
+ *
+ * DESCRIPTION
+ *
+ *    Returns TRUE if the `utf8' string of length of `utf8_len' is valid
+ *    UTF-8 encoded string, FALSE if it is not UTF-8 encoded string.
+ *
+ ***/
+bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_strcasecmp
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_utf8_strcasecmp(const char *s1, const char *s2);
+ *
+ * DESCRIPTION
+ *
+ *    The silc_utf8_strcasecmp() function compares the two strings s1 and s2,
+ *    ignoring the case of the characters.  It returns TRUE if the strings
+ *    match and FALSE if they differ.
+ *
+ *    This functions expects NULL terminated UTF-8 strings.  The strings
+ *    will be casefolded and normalized before comparing.  Certain special
+ *    Unicode characters will be ignored when comparing.
+ *
+ ***/
+bool silc_utf8_strcasecmp(const char *s1, const char *s2);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_strncasecmp
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_utf8_strcasecmp(const char *s1, const char *s2,
+ *                              SilcUInt32 n);
+ *
+ * DESCRIPTION
+ *
+ *    The silc_utf8_strcasecmp() function compares the two strings s1 and s2,
+ *    ignoring the case of the characters.  It returns TRUE if the strings
+ *    match and FALSE if they differ.
+ *
+ *    This functions expects NULL terminated UTF-8 strings.  The strings
+ *    will be casefolded and normalized before comparing.  Certain special
+ *    Unicode characters will be ignored when comparing.
+ *
+ ***/
+bool silc_utf8_strncasecmp(const char *s1, const char *s2, SilcUInt32 n);
+
+#endif /* SILCUTF8_H */
index f665344eee27d456d5e019a8044e12fe92704213..a3746f92ff8bf9f745c731cc17f99bfae5bdfb97 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -156,7 +156,7 @@ bool silc_parse_userfqdn(const char *string, char **left, char **right)
     }
   } else {
     if (left)
-      *left = strdup(string);
+      *left = silc_memdup(string, strlen(string));
   }
 
   return TRUE;
@@ -467,6 +467,25 @@ SilcUInt32 silc_hash_string(void *key, void *user_context)
   return h;
 }
 
+/* Hash UTF-8 string */
+
+SilcUInt32 silc_hash_utf8_string(void *key, void *user_context)
+{
+  unsigned char *s = (unsigned char *)key;
+  SilcUInt32 h = 0, g;
+
+  while (*s != '\0') {
+    h = (h << 4) + *s;
+    if ((g = h & 0xf0000000)) {
+      h = h ^ (g >> 24);
+      h = h ^ g;
+    }
+    s++;
+  }
+
+  return h;
+}
+
 /* Basic hash function to hash integers. May be used with the SilcHashTable. */
 
 SilcUInt32 silc_hash_uint(void *key, void *user_context)
@@ -478,14 +497,14 @@ SilcUInt32 silc_hash_uint(void *key, void *user_context)
 
 SilcUInt32 silc_hash_ptr(void *key, void *user_context)
 {
-  return (SilcUInt32)key;
+  return SILC_PTR_TO_32(key);
 }
 
 /* Hash a ID. The `user_context' is the ID type. */
 
 SilcUInt32 silc_hash_id(void *key, void *user_context)
 {
-  SilcIdType id_type = (SilcIdType)(SilcUInt32)user_context;
+  SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
   SilcUInt32 h = 0;
   int i;
 
@@ -553,7 +572,7 @@ SilcUInt32 silc_hash_client_id_hash(void *key, void *user_context)
 
 SilcUInt32 silc_hash_data(void *key, void *user_context)
 {
-  SilcUInt32 len = (SilcUInt32)user_context, h = 0;
+  SilcUInt32 len = SILC_PTR_TO_32(user_context), h = 0;
   unsigned char *data = (unsigned char *)key;
   int i;
 
@@ -569,9 +588,9 @@ SilcUInt32 silc_hash_data(void *key, void *user_context)
 SilcUInt32 silc_hash_public_key(void *key, void *user_context)
 {
   SilcPublicKey pk = (SilcPublicKey)key;
-  return (pk->len + silc_hash_string(pk->name, NULL) +
-         silc_hash_string(pk->identifier, NULL) +
-         silc_hash_data(pk->pk, (void *)pk->pk_len));
+  return (pk->len + (silc_hash_string(pk->name, NULL) ^
+                    silc_hash_string(pk->identifier, NULL) ^
+                    silc_hash_data(pk->pk, SILC_32_TO_PTR(pk->pk_len))));
 }
 
 /* Compares two strings. It may be used as SilcHashTable comparison
@@ -588,7 +607,7 @@ bool silc_hash_string_compare(void *key1, void *key2, void *user_context)
 
 bool silc_hash_id_compare(void *key1, void *key2, void *user_context)
 {
-  SilcIdType id_type = (SilcIdType)(SilcUInt32)user_context;
+  SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context);
   return (id_type == SILC_ID_CLIENT ?
          SILC_ID_COMPARE_HASH((SilcClientID *)key1, (SilcClientID *)key2) :
          SILC_ID_COMPARE_TYPE(key1, key2, id_type));
@@ -605,10 +624,21 @@ bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context)
 
 bool silc_hash_data_compare(void *key1, void *key2, void *user_context)
 {
-  SilcUInt32 len = (SilcUInt32)user_context;
+  SilcUInt32 len = SILC_PTR_TO_32(user_context);
   return !memcmp(key1, key2, len);
 }
 
+/* Compares UTF-8 string. */
+
+bool silc_hash_utf8_compare(void *key1, void *key2, void *user_context)
+{
+  int l1 = strlen((char *)key1);
+  int l2 = strlen((char *)key2);
+  if (l1 > l2)
+    l2 = l1;
+  return !memcmp(key1, key2, l2);
+}
+
 /* Compares two SILC Public keys. It may be used as SilcHashTable
    comparison function. */
 
@@ -1046,6 +1076,8 @@ static const SilcStatusMessage silc_status_messages[] = {
   { STAT(TIMEDOUT), "Service timed out" },
   { STAT(UNSUPPORTED_PUBLIC_KEY), "Unsupported public key type" },
   { STAT(OPERATION_ALLOWED), "Operation is not allowed" },
+  { STAT(BAD_SERVER), "Bad server name" },
+  { STAT(BAD_USERNAME), "Bad user name" },
 
   { 0, NULL }
 };
index 57c5b1db9434d3013ab603097fa1dfbafd241995..72aac63e4aad830e7325ed8a067b726e985bd05e 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -196,6 +196,21 @@ int silc_string_compare(char *string1, char *string2);
  ***/
 SilcUInt32 silc_hash_string(void *key, void *user_context);
 
+/****f* silcutil/SilcUtilAPI/silc_hash_utf8_string
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
+ *
+ * DESCRIPTION
+ *
+ *    Basic has function to hash UTF-8 strings. May be used with the
+ *    SilcHashTable.  Used with identifier strings.  The key is
+ *    expected to be casefolded.
+ *
+ ***/
+SilcUInt32 silc_hash_utf8_string(void *key, void *user_context);
+
 /****f* silcutil/SilcUtilAPI/silc_hash_uint
  *
  * SYNOPSIS
@@ -330,11 +345,26 @@ bool silc_hash_client_id_compare(void *key1, void *key2, void *user_context);
  ***/
 bool silc_hash_data_compare(void *key1, void *key2, void *user_context);
 
+/****f* silcutil/SilcUtilAPI/silc_hash_utf8_compare
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_hash_utf8_compare(void *key1, void *key2, void *user_context);
+ *
+ * DESCRIPTION
+ *
+ *    Compares UTF-8 strings.  Casefolded and NULL terminated strings are
+ *    expected.  May be used as SilcHashTable comparison function.
+ *
+ ***/
+bool silc_hash_utf8_compare(void *key1, void *key2, void *user_context);
+
 /****f* silcutil/SilcUtilAPI/silc_hash_public_key_compare
  *
  * SYNOPSIS
  *
- *    bool silc_hash_public_key_compare(void *key1, void *key2, void *user_context);
+ *    bool silc_hash_public_key_compare(void *key1, void *key2,
+ *                                      void *user_context);
  *
  * DESCRIPTION
  *
@@ -482,7 +512,7 @@ int silc_gettimeofday(struct timeval *p);
  *
  * SYNOPSIS
  *
- *    bool silc_compare_timeval(struct timeval *smaller, 
+ *    bool silc_compare_timeval(struct timeval *smaller,
  *                              struct timeval *bigger)
  *
  * DESCRIPTION
@@ -491,7 +521,7 @@ int silc_gettimeofday(struct timeval *p);
  *    time value is smaller than the second time value.
  *
  ***/
-bool silc_compare_timeval(struct timeval *smaller, 
+bool silc_compare_timeval(struct timeval *smaller,
                          struct timeval *bigger);
 
 /****f* silcutil/SilcUtilAPI/silc_string_regexify
index a6d6fd5bd655e33ccbdf99bf51241553e31a5b4e..6776a31c13e49273c380441b1b30b76d0b91a4b8 100644 (file)
@@ -1,6 +1,6 @@
 /*
 
-  silcvcard.c 
+  silcvcard.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
@@ -43,44 +43,44 @@ unsigned char *silc_vcard_encode(SilcVCard vcard, SilcUInt32 *vcard_len)
        "FN:", vcard->full_name, "\n",
        "N:", vcard->family_name, ";", vcard->first_name, ";",
        vcard->middle_names, ";", vcard->prefix, ";", vcard->suffix, "\n",
-       SILC_STR_END);
+       SILC_STRFMT_END);
 
   if (vcard->nickname)
     silc_buffer_strformat(&buffer,
                          "NICKNAME:", vcard->nickname, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->bday)
     silc_buffer_strformat(&buffer,
                          "BDAY:", vcard->bday, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->title)
     silc_buffer_strformat(&buffer,
                          "TITLE:", vcard->title, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->role)
     silc_buffer_strformat(&buffer,
                          "ROLE:", vcard->role, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->org_name)
     silc_buffer_strformat(&buffer,
                          "ORG:", vcard->org_name, ";", vcard->org_unit, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->categories)
     silc_buffer_strformat(&buffer,
                          "CATEGORIES:", vcard->categories, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->catclass)
     silc_buffer_strformat(&buffer,
                          "CLASS:", vcard->catclass, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->url)
     silc_buffer_strformat(&buffer,
                          "URL:", vcard->url, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->label)
     silc_buffer_strformat(&buffer,
                          "LABEL;", vcard->url, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   for (i = 0; i < vcard->num_addrs; i++) {
     silc_buffer_strformat(&buffer,
                          "ADR;TYPE=",
@@ -92,32 +92,32 @@ unsigned char *silc_vcard_encode(SilcVCard vcard, SilcUInt32 *vcard_len)
                          vcard->addrs[i].state, ";",
                          vcard->addrs[i].code, ";",
                          vcard->addrs[i].country, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   }
   for (i = 0; i < vcard->num_tels; i++) {
     silc_buffer_strformat(&buffer,
                          "TEL;TYPE=",
                          vcard->tels[i].type, ":",
                          vcard->tels[i].telnum, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   }
   for (i = 0; i < vcard->num_emails; i++) {
     silc_buffer_strformat(&buffer,
                          "EMAIL;TYPE=",
                          vcard->emails[i].type, ":",
                          vcard->emails[i].address, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   }
   if (vcard->note)
     silc_buffer_strformat(&buffer,
                          "NOTE:", vcard->note, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
   if (vcard->rev)
     silc_buffer_strformat(&buffer,
                          "REV:", vcard->rev, "\n",
-                         SILC_STR_END);
+                         SILC_STRFMT_END);
 
-  silc_buffer_strformat(&buffer, VCARD_FOOTER, SILC_STR_END);
+  silc_buffer_strformat(&buffer, VCARD_FOOTER, SILC_STRFMT_END);
 
   if (vcard_len)
     *vcard_len = buffer.truelen;
@@ -174,7 +174,7 @@ bool silc_vcard_decode(const unsigned char *data, SilcUInt32 data_len,
   unsigned char *val;
   bool has_begin = FALSE, has_end = FALSE;
   int len, i, off = 0;
-  
+
   val = (unsigned char *)data;
   while (val) {
     len = 0;
diff --git a/lib/silcutil/tests/Makefile.am b/lib/silcutil/tests/Makefile.am
new file mode 100644 (file)
index 0000000..e002573
--- /dev/null
@@ -0,0 +1,29 @@
+#
+#  Makefile.am
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2004 - 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
+
+bin_PROGRAMS =         test_silcstrutil test_silcstringprep test_silchashtable
+
+test_silcstrutil_SOURCES = test_silcstrutil.c
+test_silcstringprep_SOURCES = test_silcstringprep.c
+test_silchashtable_SOURCES = test_silchashtable.c
+
+LIBS = $(SILC_COMMON_LIBS)
+LDADD = -L.. -L../.. -lsilc
+
+include $(top_srcdir)/Makefile.defines.in
diff --git a/lib/silcutil/tests/test_silchashtable.c b/lib/silcutil/tests/test_silchashtable.c
new file mode 100644 (file)
index 0000000..47326c0
--- /dev/null
@@ -0,0 +1,297 @@
+/* Hash table tests */
+
+#include "silcincludes.h"
+
+typedef struct entry_struct {
+  char name[8];
+  int val;
+} *entry;
+
+bool dump = FALSE;
+bool auto_rehash = TRUE;
+int count = 2000;
+SilcHashTable t = NULL;
+
+SilcUInt32 hash_entry(void *key, void *user_context)
+{
+  entry e = key;
+  return e->val + silc_hash_string(e->name, NULL);
+}
+
+bool hash_compare(void *key1, void *key2, void *user_context)
+{
+  entry e = key1;
+  entry e2 = key2;
+  if (e->val == e2->val && !strcmp(e->name, e2->name))
+    return TRUE;
+  return FALSE;
+}
+
+void hash_destructor(void *key, void *context, void *user_context)
+{
+  entry e = key;
+  char *name = context;
+  if (dump)
+    SILC_LOG_DEBUG(("e=%p, e->val=%d, e->name=%s, context=%s",
+                   e, e->val, e->name, name));
+  memset(e, 'F', sizeof(*e));
+  silc_free(e);
+}
+
+bool add_entries()
+{
+  entry e;
+  int i;
+
+  SILC_LOG_DEBUG(("Adding %d entries", count));
+
+  for (i = 0; i < count; i++) {
+    e = silc_calloc(1, sizeof(*e));
+    if (!e)
+      return FALSE;
+    snprintf(e->name, sizeof(e->name), "%d", i);
+    e->val = i;
+
+    silc_hash_table_add(t, (void *)e, (void *)e->name);
+  }
+
+  SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
+
+  return TRUE;
+}
+
+bool del_entries_with_list()
+{
+  SilcHashTableList htl;
+  entry e;
+  char *name;
+
+  SILC_LOG_DEBUG(("Deleting entries with SilcHashTableList"));
+
+  silc_hash_table_list(t, &htl);
+  while (silc_hash_table_get(&htl, (void **)&e, (void **)&name)) {
+    if (!silc_hash_table_del(t, e))
+      return FALSE;
+  }
+  silc_hash_table_list_reset(&htl);
+
+  SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
+
+  return TRUE;
+}
+
+void del_foreach(void *key, void *context, void *user_context)
+{
+  entry e = key;
+  char *name = context;
+  if (dump)
+    SILC_LOG_DEBUG(("del_foreach found e=%p, e->val=%d, e->name=%s, context=%s",
+                   e, e->val, e->name, name));
+  silc_hash_table_del(t, key);
+}
+
+bool del_n_entries_foreach()
+{
+  struct entry_struct f;
+  int i;
+
+  SILC_LOG_DEBUG(("Deleting keys 0-%d with foreach", count));
+
+  for (i = 0; i < count; i++) {
+    memset(&f, 0, sizeof(f));
+    snprintf(f.name, sizeof(f.name), "%d", i);
+    f.val = i;
+
+    silc_hash_table_find_foreach(t, &f, del_foreach, NULL);
+  }
+
+  return TRUE;
+}
+
+bool del_entries_foreach()
+{
+  SILC_LOG_DEBUG(("Deleting all entries with foreach"));
+  silc_hash_table_foreach(t, del_foreach, NULL);
+  return TRUE;
+}
+
+bool alloc_table()
+{
+  SILC_LOG_DEBUG(("Allocating hash table with %d entries (%s)",
+                 count, auto_rehash ? "auto rehash" : "no auto rehash"));
+
+  t = silc_hash_table_alloc(0, hash_entry, NULL,
+                           hash_compare, NULL,
+                           hash_destructor, NULL, auto_rehash);
+
+  if (!add_entries())
+    return FALSE;
+
+  SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
+
+  if (silc_hash_table_count(t) != count) {
+    SILC_LOG_DEBUG(("Wrong table count %d", count));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+bool delete_table_with_list()
+{
+
+  SILC_LOG_DEBUG(("Deleting entries with SilcHashTableList"));
+
+  if (!del_entries_with_list())
+    return FALSE;
+
+  SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
+
+  if (silc_hash_table_count(t) != 0) {
+    SILC_LOG_DEBUG(("Wrong table count %d != 0", count));
+    return FALSE;
+  }
+
+  silc_hash_table_free(t);
+  t = NULL;
+
+  return TRUE;
+}
+
+bool find_entries()
+{
+  struct entry_struct f;
+  entry e;
+  char *name;
+  int i;
+
+  SILC_LOG_DEBUG(("Finding %d entries", count));
+
+  for (i = 0; i < count; i++) {
+    memset(&f, 0, sizeof(f));
+    snprintf(f.name, sizeof(f.name), "%d", i);
+    f.val = i;
+
+    /* Find */
+    if (!silc_hash_table_find(t, &f, (void **)&e, (void **)&name))
+      return FALSE;
+
+    /* Find itself with context */
+    if (!silc_hash_table_find_by_context(t, e, e->name, NULL))
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+bool dump_table()
+{
+  SilcHashTableList htl;
+  entry e;
+  char *name;
+  bool dumpped = FALSE;
+
+  SILC_LOG_DEBUG(("Dumping hash table entries"));
+
+  silc_hash_table_list(t, &htl);
+  while (silc_hash_table_get(&htl, (void **)&e, (void **)&name)) {
+    dumpped = TRUE;
+    if (dump)
+      SILC_LOG_DEBUG(("e=%p, e->val=%d, e->name=%s, context=%s",
+                     e, e->val, e->name, name));
+  }
+  silc_hash_table_list_reset(&htl);
+
+  return dumpped;
+}
+
+int main(int argc, char **argv)
+{
+  bool success = FALSE;
+  int i;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_debug = 1;
+    silc_debug_hexdump = 1;
+    silc_log_set_debug_string("*table*");
+  }
+
+  if (argc > 1 && !strcmp(argv[1], "-D")) {
+    silc_debug = 1;
+    dump = TRUE;
+    silc_log_set_debug_string("*table*");
+  }
+
+  if (!alloc_table())
+    goto err;
+  if (!dump_table())
+    goto err;
+  if (!delete_table_with_list())
+    goto err;
+
+  count = 1387;
+  auto_rehash = FALSE;
+  if (!alloc_table())
+    goto err;
+  if (!dump_table())
+    goto err;
+  SILC_LOG_DEBUG(("rehash"));
+  silc_hash_table_rehash(t, 0);
+  SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
+  SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
+  if (!delete_table_with_list())
+    goto err;
+
+  count = 999;
+  auto_rehash = TRUE;
+  if (!alloc_table())
+    goto err;
+  count = 3999;
+  if (!add_entries())
+    goto err;
+  SILC_LOG_DEBUG(("rehash"));
+  silc_hash_table_rehash(t, 0);
+  SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
+  SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
+  if (!del_entries_with_list())
+    goto err;
+  SILC_LOG_DEBUG(("rehash"));
+  silc_hash_table_rehash(t, 0);
+  SILC_LOG_DEBUG(("Hash table entry count: %d", silc_hash_table_count(t)));
+  SILC_LOG_DEBUG(("Hash table size: %d", silc_hash_table_size(t)));
+  count = 999;
+  if (!add_entries())
+    goto err;
+  /* Adding duplicates */
+  for (i = 0; i < 30; i++) {
+    count = 50;
+    if (!add_entries())
+      goto err;
+  }
+  count = 700;
+  if (!find_entries())
+    goto err;
+  count = 500;
+  if (!del_n_entries_foreach())
+    goto err;
+  count = 999;
+  if (!add_entries())
+    goto err;
+  count = 700;
+  if (!find_entries())
+    goto err;
+  if (!dump_table())
+    goto err;
+  if (!del_entries_foreach())
+    goto err;
+  if (!delete_table_with_list())
+    goto err;
+
+  success = TRUE;
+
+ err:
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}
diff --git a/lib/silcutil/tests/test_silcstringprep.c b/lib/silcutil/tests/test_silcstringprep.c
new file mode 100644 (file)
index 0000000..26ff2aa
--- /dev/null
@@ -0,0 +1,166 @@
+/* Stringprep tests */
+
+#include "silcincludes.h"
+
+typedef struct {
+  const char *comment;
+  const char *in;
+  const char *out;
+  int ret;
+  int enc;
+} test_st;
+
+const test_st tests[] = {
+  {"Prohibited *",
+   "foo*", "", SILC_STRINGPREP_ERR_PROHIBITED},
+  {"Prohibited ?",
+   "?foo", "", SILC_STRINGPREP_ERR_PROHIBITED},
+  {"Prohibited ,",
+   "f,f", "", SILC_STRINGPREP_ERR_PROHIBITED},
+  {"Prohibited !",
+   "!", "", SILC_STRINGPREP_ERR_PROHIBITED},
+  {"Prohibited @",
+   "foo@faa", "", SILC_STRINGPREP_ERR_PROHIBITED},
+  {"Normal casefold",
+   "Foobbeli-BofJFlkJDF", "foobbeli-bofjflkjdf"},
+  {"Nothing",
+   "sauna.silcnet.org", "sauna.silcnet.org"},
+  {"Nothing with #",
+   "#silc", "#silc"},
+  {"Locale test",
+   "Päivää", "päivää", 0, SILC_STRING_LOCALE},
+  {"Locale test2",
+   "#öäöö/&#\\#(&(&#(.äöäÄÖäÄÖÄÖ^'", 
+   "#öäöö/&#\\#(&(&#(.äöääöääöäö^'", 0, SILC_STRING_LOCALE},
+
+  /* Some libidn tests */
+  {"Map to nothing",
+   "foo\xC2\xAD\xCD\x8F\xE1\xA0\x86\xE1\xA0\x8B"
+   "bar" "\xE2\x80\x8B\xE2\x81\xA0" "baz\xEF\xB8\x80\xEF\xB8\x88"
+   "\xEF\xB8\x8F\xEF\xBB\xBF", "foobarbaz"},
+  {"Case folding ASCII U+0043 U+0041 U+0046 U+0045", "CAFE", "cafe"},
+  {"Case folding 8bit U+00DF (german sharp s)", "\xC3\x9F", "ss"},
+  {"Case folding U+0130 (turkish capital I with dot)",
+   "\xC4\xB0", "i\xcc\x87"},
+  {"ASCII space character U+0020", "\x20", "\x20",
+   SILC_STRINGPREP_ERR_PROHIBITED},
+  {"ASCII control characters U+0010 U+007F", "\x10\x7F", "\x10\x7F",
+   SILC_STRINGPREP_ERR_PROHIBITED},
+};
+
+const test_st tests_norm[] = {
+  {"Casefold 1",
+   "Pekka Riikonen", "pekka riikonen"},
+  {"Casefold 2",
+   "PEKKA RIIKONEN", "pekka riikonen"},
+  {"Casefold 3",
+   "pekka riikonen", "pekka riikonen"},
+  {"Casefold 4",
+   "#ksPPPAA", "#kspppaa"},
+  {"Normal casefold",
+   "Foobbeli-BofJFlkJDF", "foobbeli-bofjflkjdf"},
+  {"Nothing",
+   "sauna.silcnet.org", "sauna.silcnet.org"},
+  {"Locale test",
+   "Päivää", "päivää", 0, SILC_STRING_LOCALE},
+  {"Locale test2",
+   "#öäöö/&#\\#(&(&#(.äöäÄÖäÄÖÄÖ^'", 
+   "#öäöö/&#\\#(&(&#(.äöääöääöäö^'", 0, SILC_STRING_LOCALE},
+};
+
+int main(int argc, char **argv)
+{
+  bool success = FALSE;
+  int i, enc;
+  unsigned char *out = NULL;
+  SilcUInt32 out_len;
+  SilcStringprepStatus ret;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_debug = 1;
+    silc_debug_hexdump = 1;
+    silc_log_set_debug_string("*stringprep*,*utf8*");
+  }
+
+  SILC_LOG_DEBUG(("--- Identifier string tests"));
+
+  for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+    SILC_LOG_DEBUG(("Test case %d", i));
+    SILC_LOG_DEBUG((" %d: %s", i, tests[i].comment));
+    SILC_LOG_DEBUG((" %d: in: %s", i, tests[i].in));
+    SILC_LOG_DEBUG((" %d: out: %s", i, tests[i].out));
+    SILC_LOG_DEBUG((" %d: ret: %d", i, tests[i].ret));
+
+    if (!tests[i].enc)
+      enc = SILC_STRING_UTF8;
+    else
+      enc = tests[i].enc;
+    ret = silc_stringprep(tests[i].in, strlen(tests[i].in),
+                         enc, SILC_IDENTIFIER_PREP, 0,
+                         &out, &out_len, enc);
+    if (ret != SILC_STRINGPREP_OK) {
+      if (tests[i].ret != SILC_STRINGPREP_OK) {
+        SILC_LOG_DEBUG((" %d: Expected ret %d", i, ret));
+      } else {
+        SILC_LOG_DEBUG(("%d: Error: %d", i, ret));
+        goto err;
+      }
+    } else {
+      SILC_LOG_DEBUG((" %d: prepared out: %s", i, out));
+      SILC_LOG_HEXDUMP((" %d: prepared dump", i), out, out_len);
+      if (memcmp(out, tests[i].out, out_len)) {
+        SILC_LOG_DEBUG((" %d: Output mismatch", i));
+        goto err;
+      }
+    }
+    SILC_LOG_DEBUG((" %d: Output match", i));
+
+    silc_free(out);
+    out = NULL;
+  }
+
+  SILC_LOG_DEBUG(("--- Casefold tests"));
+
+  for (i = 0; i < sizeof(tests_norm) / sizeof(tests_norm[0]); i++) {
+    SILC_LOG_DEBUG(("Test case %d", i));
+    SILC_LOG_DEBUG((" %d: %s", i, tests_norm[i].comment));
+    SILC_LOG_DEBUG((" %d: in: %s", i, tests_norm[i].in));
+    SILC_LOG_DEBUG((" %d: out: %s", i, tests_norm[i].out));
+    SILC_LOG_DEBUG((" %d: ret: %d", i, tests_norm[i].ret));
+
+    if (!tests_norm[i].enc)
+      enc = SILC_STRING_UTF8;
+    else
+      enc = tests_norm[i].enc;
+    ret = silc_stringprep(tests_norm[i].in, strlen(tests_norm[i].in),
+                         enc, SILC_CASEFOLD_PREP, 0,
+                         &out, &out_len, enc);
+    if (ret != SILC_STRINGPREP_OK) {
+      if (tests_norm[i].ret != SILC_STRINGPREP_OK) {
+        SILC_LOG_DEBUG((" %d: Expected ret %d", i, ret));
+      } else {
+        SILC_LOG_DEBUG(("%d: Error: %d", i, ret));
+        goto err;
+      }
+    } else {
+      SILC_LOG_DEBUG((" %d: prepared out: %s", i, out));
+      SILC_LOG_HEXDUMP((" %d: prepared dump", i), out, out_len);
+      if (memcmp(out, tests_norm[i].out, out_len)) {
+        SILC_LOG_DEBUG((" %d: Output mismatch", i));
+        goto err;
+      }
+    }
+    SILC_LOG_DEBUG((" %d: Output match", i));
+
+    silc_free(out);
+    out = NULL;
+  }
+
+  success = TRUE;
+
+ err:
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}
diff --git a/lib/silcutil/tests/test_silcstrutil.c b/lib/silcutil/tests/test_silcstrutil.c
new file mode 100644 (file)
index 0000000..f7b4faf
--- /dev/null
@@ -0,0 +1,140 @@
+/* UTF-8 decoding tests */
+
+#include "silcincludes.h"
+
+#define utf8fail(n, data, len)                 \
+const unsigned char u##n[] = (data);           \
+int u##n##l = len;
+
+#define utf8failc(n)                                                         \
+do {                                                                         \
+  if (!silc_utf8_valid(u##n, u##n##l))                                       \
+    SILC_LOG_DEBUG(("%d: not valid UTF-8, correctly detected, no error", n)); \
+  else {                                                                     \
+    SILC_LOG_DEBUG(("%d: parser did not detect malformed UTF-8, error", n));  \
+    goto err;                                                                \
+  }                                                                          \
+} while(0)
+
+/* UTF-8 Test vectors that MUST fail */
+utf8fail(1, "\x80", 1);
+utf8fail(2, "\xbf", 1);
+utf8fail(3, "\xfe", 1);
+utf8fail(4, "\xff", 1);
+utf8fail(5, "\xfe\xfe\xff\xff", 4);
+utf8fail(6, "\xc0\xa0", 2);
+utf8fail(7, "\xe0\x80\xaf", 3);
+utf8fail(8, "\xf0\x80\x80\xaf", 4);
+utf8fail(9, "\xf8\x80\x80\x80\xaf", 5);
+utf8fail(10, "\xfc\x80\x80\x80\x80\xaf", 6);
+utf8fail(11, "\xc0\x80", 2);
+utf8fail(12, "\xe0\x80\x80", 3);
+utf8fail(13, "\xf0\x80\x80\x80", 4);
+utf8fail(14, "\xf8\x80\x80\x80\x80", 5);
+utf8fail(15, "\xfc\x80\x80\x80\x80\x80", 6);
+utf8fail(16, "\xc1\xbf", 2);
+utf8fail(17, "\xe0\x9f\xbf", 3);
+utf8fail(18, "\xf0\x8f\xbf\xbf", 4);
+utf8fail(19, "\xf8\x87\xbf\xbf\xbf", 5);
+utf8fail(20, "\xfc\x83\xbf\xbf\xbf\xbf", 6);
+utf8fail(21, "\xed\xa0\x80", 3);
+utf8fail(22, "\xed\xad\xbf", 3);
+utf8fail(23, "\xed\xae\x80", 3);
+utf8fail(24, "\xed\xaf\xbf", 3);
+utf8fail(25, "\xed\xb0\x80", 3);
+utf8fail(26, "\xed\xbe\x80", 3);
+utf8fail(27, "\xed\xbf\xbf", 3);
+utf8fail(28, "\xfc\x20\xfd\x20", 4);
+utf8fail(29, "\xf8\xf9\xfa\xfb", 4);
+utf8fail(30, "\xf0\x20\xf9\x20\xfa\x20\xfb\x20", 8);
+
+int main(int argc, char **argv)
+{
+  bool success = FALSE;
+  unsigned char *s1, *s2, *s3, *s4;
+  int l;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_debug = 1;
+    silc_debug_hexdump = 1;
+    silc_log_set_debug_string("*strutil*");
+  }
+
+  /* Failure tests */
+  utf8failc(1);  utf8failc(2);
+  utf8failc(3);  utf8failc(4);
+  utf8failc(5);  utf8failc(6);
+  utf8failc(7);  utf8failc(8);
+  utf8failc(9);  utf8failc(10);
+  utf8failc(11);  utf8failc(12);
+  utf8failc(13);  utf8failc(14);
+  utf8failc(15);  utf8failc(16);
+  utf8failc(17);  utf8failc(18);
+  utf8failc(19);  utf8failc(20);
+  utf8failc(21);  utf8failc(22);
+  utf8failc(23);  utf8failc(24);
+  utf8failc(25);  utf8failc(26);
+  utf8failc(27);  utf8failc(28);
+  utf8failc(29);  utf8failc(30);
+
+  /* LDAP DN simple test */
+  s1 = "#&?*Pekka, \\Riikonen, <foobar@foobar.com>\xc4\x8d\\ ";
+  SILC_LOG_DEBUG(("s1 = %s", s1));
+
+  /* To LDAP DN */
+  l = silc_utf8_decoded_len(s1, strlen(s1), SILC_STRING_LDAP_DN);
+  if (!l)
+    goto err;
+  s3 = silc_calloc(l + 1, sizeof(*s3));
+  silc_utf8_decode(s1, strlen(s1), SILC_STRING_LDAP_DN, s3, l);
+  SILC_LOG_DEBUG(("ldapdn = %s", s3));
+
+  /* To UTF-8 */
+  l = silc_utf8_encoded_len(s3, strlen(s3), SILC_STRING_LDAP_DN);
+  if (!l)
+    goto err;  
+  s4 = silc_calloc(l + 1, sizeof(*s4));
+  silc_utf8_encode(s3, strlen(s3), SILC_STRING_LDAP_DN, s4, l);
+  SILC_LOG_DEBUG(("utf8 = %s", s4));
+
+  if (memcmp(s4, s1, strlen(s4))) {
+    SILC_LOG_DEBUG(("UTF-8 mismatch"));
+    goto err;
+  }
+  silc_free(s3);
+  silc_free(s4);
+
+  /* UTF-8 strcasecmp test */
+  SILC_LOG_DEBUG(("silc_utf8_strcasecmp test"));
+  s1 = "Päivää vuan Yrjö";
+  s2 = "PÄIVÄÄ VUAN YRJÖ";
+  l = silc_utf8_encoded_len(s1, strlen(s1), SILC_STRING_LOCALE);
+  if (!l)
+    goto err;  
+  s3 = silc_calloc(l + 1, sizeof(*s3));
+  silc_utf8_encode(s1, strlen(s1), SILC_STRING_LOCALE, s3, l);
+
+  l = silc_utf8_encoded_len(s2, strlen(s2), SILC_STRING_LOCALE);
+  if (!l)
+    goto err;  
+  s4 = silc_calloc(l + 1, sizeof(*s4));
+  silc_utf8_encode(s2, strlen(s2), SILC_STRING_LOCALE, s4, l);
+
+  SILC_LOG_DEBUG(("%s == %s", s3, s4));
+  if (!silc_utf8_strcasecmp(s3, s4)) {
+    SILC_LOG_DEBUG(("mismatch"));
+    goto err;
+  }
+  SILC_LOG_DEBUG(("match"));
+
+  silc_free(s3);
+  silc_free(s4);
+
+  success = TRUE;
+
+ err:
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}
index b753ac5118be0430f4e795e63adb38611527835b..d2e52e936a1d75ff444926ab27e8d6e75bbc949d 100644 (file)
@@ -197,6 +197,14 @@ int silc_net_create_connection(const char *local_ip, int port,
   /* Connect to the host */
   rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost));
   if (rval < 0) {
+    /* retry using an IPv4 adress, if IPv6 didn't work */
+    if (prefer_ipv6 && silc_net_is_ip6(ip_addr)) {
+      shutdown(sock, 2);
+      close(sock);
+
+      prefer_ipv6 = FALSE;
+      goto retry;
+    }
     SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
     shutdown(sock, 2);
     close(sock);
@@ -272,6 +280,15 @@ int silc_net_create_connection_async(const char *local_ip, int port,
   rval = connect(sock, &desthost.sa, SIZEOF_SOCKADDR(desthost));
   if (rval < 0) {
     if (errno !=  EINPROGRESS) {
+      /* retry using an IPv4 adress, if IPv6 didn't work */
+      if (prefer_ipv6 && silc_net_is_ip6(ip_addr)) {
+        shutdown(sock, 2);
+        close(sock);
+
+        prefer_ipv6 = FALSE;
+        goto retry;
+      }
+
       SILC_LOG_ERROR(("Cannot connect to remote host: %s", strerror(errno)));
       shutdown(sock, 2);
       close(sock);
index 846cfa4bf68e2aac91751e0e83253dbeeca5e556..d27ceacdb527beb3de1eef7ac02dc6305d02e7e7 100644 (file)
@@ -4,13 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1998 - 2001 Pekka Riikonen
+  Copyright (C) 1998 - 2004 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -24,7 +23,7 @@
 
 /* Calls normal select() system call. */
 
-int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, 
+int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count,
                struct timeval *timeout)
 {
   fd_set in, out;
@@ -119,10 +118,10 @@ void *silc_schedule_internal_init(SilcSchedule schedule,
     return NULL;
   }
 
-  internal->wakeup_task = 
+  internal->wakeup_task =
     silc_schedule_task_add(schedule, internal->wakeup_pipe[0],
                           silc_schedule_wakeup_cb, internal,
-                          0, 0, SILC_TASK_FD, 
+                          0, 0, SILC_TASK_FD,
                           SILC_TASK_PRI_NORMAL);
   if (!internal->wakeup_task) {
     SILC_LOG_ERROR(("Could not add a wakeup task, threads won't work"));
@@ -138,6 +137,9 @@ void *silc_schedule_internal_init(SilcSchedule schedule,
   return (void *)internal;
 }
 
+void silc_schedule_internal_signals_block(void *context);
+void silc_schedule_internal_signals_unblock(void *context);
+
 /* Uninitializes the platform specific scheduler context. */
 
 void silc_schedule_internal_uninit(void *context)
@@ -180,7 +182,9 @@ void silc_schedule_internal_signal_register(void *context,
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  SILC_LOG_DEBUG(("Registering signal %d", signal));
+
+  silc_schedule_internal_signals_block(context);
 
   for (i = 0; i < SIGNAL_COUNT; i++) {
     if (!internal->signal_call[i].signal) {
@@ -192,7 +196,7 @@ void silc_schedule_internal_signal_register(void *context,
     }
   }
 
-  sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL);
+  silc_schedule_internal_signals_unblock(context);
   sigaddset(&internal->signals, signal);
 }
 
@@ -207,7 +211,9 @@ void silc_schedule_internal_signal_unregister(void *context,
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  SILC_LOG_DEBUG(("Unregistering signal %d", signal));
+
+  silc_schedule_internal_signals_block(context);
 
   for (i = 0; i < SIGNAL_COUNT; i++) {
     if (internal->signal_call[i].signal == signal &&
@@ -220,7 +226,7 @@ void silc_schedule_internal_signal_unregister(void *context,
     }
   }
 
-  sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL);
+  silc_schedule_internal_signals_unblock(context);
   sigdelset(&internal->signals, signal);
 }
 
@@ -234,16 +240,19 @@ void silc_schedule_internal_signal_call(void *context, SilcUInt32 signal)
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  silc_schedule_internal_signals_block(context);
 
   for (i = 0; i < SIGNAL_COUNT; i++) {
-    if (internal->signal_call[i].signal == signal)
+    if (internal->signal_call[i].signal == signal) {
       internal->signal_call[i].call = TRUE;
+      SILC_LOG_DEBUG(("Scheduling signal %d to be called",
+                     internal->signal_call[i].signal));
+    }
   }
 
-  sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL);
+  silc_schedule_internal_signals_unblock(context);
 }
-                                        
+
 /* Call all signals */
 
 void silc_schedule_internal_signals_call(void *context,
@@ -252,14 +261,18 @@ void silc_schedule_internal_signals_call(void *context,
   SilcUnixScheduler internal = (SilcUnixScheduler)context;
   int i;
 
+  SILC_LOG_DEBUG(("Start"));
+
   if (!internal)
     return;
 
-  sigprocmask(SIG_BLOCK, &internal->signals, &internal->signals_blocked);
+  silc_schedule_internal_signals_block(context);
 
   for (i = 0; i < SIGNAL_COUNT; i++) {
     if (internal->signal_call[i].call &&
         internal->signal_call[i].callback) {
+      SILC_LOG_DEBUG(("Calling signal %d callback",
+                     internal->signal_call[i].signal));
       internal->signal_call[i].callback(schedule, internal->app_context,
                                        SILC_TASK_INTERRUPT,
                                        internal->signal_call[i].signal,
@@ -268,7 +281,7 @@ void silc_schedule_internal_signals_call(void *context,
     }
   }
 
-  sigprocmask(SIG_SETMASK, &internal->signals_blocked, NULL);
+  silc_schedule_internal_signals_unblock(context);
 }
 
 /* Block registered signals in scheduler. */
index 26d9dd73a15e362f138f25281288c11f059ae815..a5d8c4d5bd67b2d484458a605be04382801fa914 100644 (file)
@@ -4,13 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -22,7 +21,7 @@
 #include "silcincludes.h"
 
 /* Writes data from encrypted buffer to the socket connection. If the
-   data cannot be written at once, it will be written later with a timeout. 
+   data cannot be written at once, it will be written later with a timeout.
    The data is written from the data section of the buffer, not from head
    or tail section. This automatically pulls the data section towards end
    after writing the data. */
@@ -34,7 +33,7 @@ int silc_socket_write(SilcSocketConnection sock)
   SilcBuffer src = sock->outbuf;
 
   if (!src)
-    return -2;
+    return -1;
   if (SILC_IS_DISABLED(sock))
     return -1;
 
@@ -72,12 +71,15 @@ int silc_socket_write(SilcSocketConnection sock)
 
 SILC_TASK_CALLBACK(silc_socket_read_qos)
 {
-  SilcSocketConnection sock = context;
-  sock->qos->applied = TRUE;
+  SilcSocketConnectionQos qos = context;
+  SilcSocketConnection sock = qos->sock;
+  qos->applied = TRUE;
   if (sock->users > 1)
-    silc_schedule_set_listen_fd(sock->qos->schedule, sock->sock,
+    silc_schedule_set_listen_fd(qos->schedule, sock->sock,
                                (SILC_TASK_READ | SILC_TASK_WRITE), TRUE);
-  sock->qos->applied = FALSE;
+  else
+    silc_schedule_unset_listen_fd(qos->schedule, sock->sock);
+  qos->applied = FALSE;
   silc_socket_free(sock);
 }
 
@@ -108,14 +110,15 @@ int silc_socket_read(SilcSocketConnection sock)
 
       if (sock->inbuf->len - len > sock->qos->read_limit_bytes) {
        /* Seems we need to apply QoS for the remaining data as well */
+       silc_socket_dup(sock);
        silc_schedule_task_add(sock->qos->schedule, sock->sock,
-                              silc_socket_read_qos, silc_socket_dup(sock),
+                              silc_socket_read_qos, sock->qos,
                               sock->qos->limit_sec, sock->qos->limit_usec,
                               SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
        silc_schedule_unset_listen_fd(sock->qos->schedule, sock->sock);
-      
+
        /* Hide the rest of the data from the buffer. */
-       sock->qos->data_len = (sock->inbuf->len - len - 
+       sock->qos->data_len = (sock->inbuf->len - len -
                               sock->qos->read_limit_bytes);
        silc_buffer_push_tail(sock->inbuf, sock->qos->data_len);
       }
@@ -153,10 +156,10 @@ int silc_socket_read(SilcSocketConnection sock)
 
   if (!sock->inbuf)
     sock->inbuf = silc_buffer_alloc(SILC_SOCKET_BUF_SIZE);
-  
+
   /* If the data does not fit to the buffer reallocate it */
   if ((sock->inbuf->end - sock->inbuf->tail) < len)
-    sock->inbuf = silc_buffer_realloc(sock->inbuf, sock->inbuf->truelen + 
+    sock->inbuf = silc_buffer_realloc(sock->inbuf, sock->inbuf->truelen +
                                      (len * 2));
   silc_buffer_put_tail(sock->inbuf, buf, len);
   silc_buffer_pull_tail(sock->inbuf, len);
@@ -179,8 +182,9 @@ int silc_socket_read(SilcSocketConnection sock)
 
     /* If we are not withing rate limit apply QoS for the read data */
     if (sock->qos->cur_rate > sock->qos->read_rate) {
+      silc_socket_dup(sock);
       silc_schedule_task_add(sock->qos->schedule, sock->sock,
-                            silc_socket_read_qos, silc_socket_dup(sock),
+                            silc_socket_read_qos, sock->qos,
                             sock->qos->limit_sec, sock->qos->limit_usec,
                             SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
       silc_schedule_unset_listen_fd(sock->qos->schedule, sock->sock);
@@ -198,8 +202,9 @@ int silc_socket_read(SilcSocketConnection sock)
     } else {
       /* Check the byte limit, and do not return more than allowed */
       if (sock->inbuf->len > sock->qos->read_limit_bytes) {
+       silc_socket_dup(sock);
        silc_schedule_task_add(sock->qos->schedule, sock->sock,
-                              silc_socket_read_qos, silc_socket_dup(sock),
+                              silc_socket_read_qos, sock->qos,
                               sock->qos->limit_sec, sock->qos->limit_usec,
                               SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
        silc_schedule_unset_listen_fd(sock->qos->schedule, sock->sock);
index 22445aef9bb1cbe5b869c0e1d58c1a49571627a4..c3dedee37270ebcd574a59be92023d798fafed3e 100644 (file)
@@ -53,7 +53,8 @@
 int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, struct timeval *timeout)
 {
   HANDLE handles[MAXIMUM_WAIT_OBJECTS];
-  DWORD ready, curtime, timeo;
+  DWORD ready, curtime;
+  LONG timeo;
   int nhandles = 0, i;
   MSG msg;
 
@@ -99,6 +100,7 @@ int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, struct timeval *timeou
       KillTimer(NULL, timer);
       if (timeo != INFINITE) {
        timeo -= GetTickCount() - curtime;
+       curtime = GetTickCount();
        if (timeo < 0)
          timeo = 0;
       }
@@ -137,6 +139,7 @@ int silc_select(SilcScheduleFd fds, SilcUInt32 fds_count, struct timeval *timeou
        return and we will give the wait another try. */
     if (timeo != INFINITE) {
       timeo -= GetTickCount() - curtime;
+      curtime = GetTickCount();
       if (timeo < 0)
        timeo = 0;
     }
index fef2f8fb687c895124ff0c77a23d840db727be8d..0fb3f204755132a8dd01ebccf7e455a3e7af7490 100644 (file)
@@ -65,7 +65,7 @@ int silc_gettimeofday(struct timeval *tv)
 char *silc_get_username(void)
 {
   DWORD maxlen = 128;
-  char username[maxlen];
+  char username[128];
   GetUserName(username, &maxlen);
   return strdup(username);
 }
diff --git a/prepare b/prepare
deleted file mode 100755 (executable)
index 397bdca..0000000
--- a/prepare
+++ /dev/null
@@ -1,158 +0,0 @@
-#! /bin/sh
-#
-#  prepare
-#
-#  Author: Pekka Riikonen <priikone@silcnet.org>
-#
-#  Copyright (C) 2000 - 2002 Pekka Riikonen
-#
-#  This program is free software; you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; version 2 of the License.
-#
-#  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 General Public License for more details.
-#
-
-#
-# Prepares SILC source tree for configuration and compilation. This is
-# done only after checkout from CVS. This is only for developers of SILC
-# and will never appear in public distribution. When creating distributions
-# this is always run first. After the distribution is created all
-# temporary files (including these prepare* scripts) are removed.
-#
-
-#
-# Usage: ./prepare [<distribution> <package version>]
-#
-# If <package version> is omitted <base version> is used as package
-# version.  The package version appears in the package name and in those
-# distributions that used the SILC_DIST_VERSION_STRING define in the
-# code.  The base version is the SILC_VERSION_STRING define.
-#
-
-#
-# SILC Distribution versions. Set here or give the version on the command
-# line as argument.
-#
-SILC_VERSION=0.9.10                    # Base version
-
-#############################################################################
-
-echo "Preparing SILC source tree for configuration and compilation..."
-
-distribution=$1
-if test "$distribution" = ""; then
-  distribution="toolkit";
-fi
-
-dist_version=$2
-if test "$dist_version" = ""; then
-  dist_version=$SILC_VERSION
-fi
-
-
-echo "Preparing $distribution distribution version $dist_version"
-
-#
-# Go though the subdirs and create the Makefile.ams from the
-# Makefile.am.pre files.
-#
-subdirs=`grep "$distribution"_SUBDIRS= distributions |cut -d=  -f2`
-ed=`grep "$distribution"_EXTRA_DIST= distributions |cut -d=  -f2`
-sed -e "/SILC_DISTRIBUTION_EXTRA/s,,$ed," Makefile.am.pre >Makefile.am
-path=`pwd`
-for i in $subdirs
-do
-  cd $i
-  sub=`grep "$distribution"_SUBDIRS_"$i"= $path/distributions |cut -d=  -f2`
-  if test "$sub" = ""; then
-    cd $path
-    continue;
-  fi
-  if [ -f Makefile.am.pre ]; then
-    sed -e "/SILC_DISTRIBUTION_SUBDIRS/s//$sub/" -e "/SILC_DISTRIBUTION_SUBDIRS/s//$sub/" Makefile.am.pre >Makefile.am 2>/dev/null
-  fi
-  cd $path
-done
-cd $path
-
-
-#
-# Replace version string, package name and distribution infos, and create 
-# the actual configure.in
-#
-echo "# Automatically generated by ./prepare from configure.in.pre. Do not edit!" >configure.in2
-sed -e "/SILC_DISTRIBUTION_SUBDIRS/s//$subdirs/" -e "/SILC_VERSION/s//$dist_version/" -e "/SILC_PACKAGE/s//silc-"$distribution"/" configure.in.pre >>configure.in2
-
-#
-# Create also the acconfig.h for the distribution. Note that this sets
-# also dist labels for distributions that are not defined.
-#
-cp acconfig.h.pre acconfig.h
-dists=`grep DISTRIBUTIONS= distributions |cut -d=  -f2`
-touch am_cond
-for i in $dists
-do
-  dl=`grep "$i"_DISTLABEL= distributions |cut -d=  -f2`
-  echo "#undef $dl" >>acconfig.h
-  if test "$i" = "$distribution"; then
-    echo "AM_CONDITIONAL($dl, test xtrue = xtrue)" >>am_cond
-  else
-    echo "AM_CONDITIONAL($dl, test xtrue = xfalse)" >>am_cond
-  fi
-done
-
-sed '/SILC_DIST_DEFINE/ r am_cond' configure.in2 >configure.in3
-dl=`grep "$distribution"_DISTLABEL= distributions |cut -d=  -f2`
-sed -e "/SILC_DIST_DEFINE/s//$dl/" configure.in3 >configure.in
-rm -f configure.in2 configure.in3 am_cond
-
-
-#
-# Prepare the Makefile.defines
-#
-cp Makefile.defines.pre Makefile.defines.in
-cp Makefile.defines_int.pre Makefile.defines_int.in
-cp Makefile.defines.in irssi
-cp Makefile.defines_int.in irssi
-cp Makefile.defines.in lib/silcmath/mpi
-cp Makefile.defines_int.in lib/silcmath/mpi
-
-aclocal
-autoconf
-autoheader >/dev/null 2>/dev/null
-libtoolize --automake --copy
-automake
-
-echo "Preparing mpi"
-cd lib/silcmath/mpi
-aclocal
-autoconf
-autoheader >/dev/null 2>/dev/null
-libtoolize --automake --copy
-automake >/dev/null 2>/dev/null
-cd ../../..
-
-file=includes/version_internal.h
-echo "/* Automatically generated by ./prepare */" >$file
-echo "#define SILC_VERSION_STRING \"$dist_version\"" >>$file
-echo "#define SILC_DIST_VERSION_STRING \"$dist_version\"" >>$file
-echo "#define SILC_PROTOCOL_VERSION_STRING \"SILC-1.2-$dist_version $distribution\"" >>$file
-echo "#define SILC_NAME \"SILC $distribution\"" >>$file
-
-# preparing irssi
-echo "Preparing irssi"
-cd irssi
-sh autogen.sh 2>/dev/null 1>/dev/null
-cd ..
-file=irssi/irssi-version.h.in
-version_date=`date +%Y%m%d`
-echo "/* automatically created by autogen.sh */" > $file
-echo "#define IRSSI_VERSION \"$dist_version (Irssi base: @VERSION@ - SILC base: SILC $dist_version)\"" >>$file
-echo "#define IRSSI_VERSION_DATE $version_date" >> $file
-echo "#define IRSSI_VERSION_TIME $version_date" >> $file
-
-echo "Done, now run ./configure and make."
diff --git a/prepare-clean b/prepare-clean
deleted file mode 100755 (executable)
index a07ab1c..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#! /bin/sh
-#
-#  prepare-clean
-#
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
-#
-#  Copyright (C) 2000 Pekka Riikonen
-#
-#  This program is free software; you can redistribute it and/or modify
-#  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, 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 General Public License for more details.
-#
-
-#
-# Removes *all* automatically generated files so that after calling this
-# the tree is completely clean and can be prepared for configuration
-# and compilation by calling ./prepare.
-#
-
-if [ -z "$MAKE" ]; then
-       MAKE=`which gmake`
-       if [ -z "$MAKE" ]; then
-               MAKE=`which make`
-               if [ -z "$MAKE" ]; then
-                       echo "Error, no [g]make in your path."
-                       exit 0
-               fi
-       fi
-fi
-echo "Using $MAKE as a make program..."
-
-echo "Cleaning entire SILC source tree..."
-echo "All errors and warnings may be safely ignored."
-$MAKE clean -k
-$MAKE distclean -k
-rm -f ltcf*
-rm -f Makefile.am
-rm -f Makefile.defines
-rm -f Makefile.defines.in
-rm -f Makefile.defines_int
-rm -f Makefile.defines_int.in
-rm -f acconfig.h
-rm -f irssi/Makefile.defines
-rm -f irssi/Makefile.defines.in
-rm -f irssi/Makefile.defines_int
-rm -f irssi/Makefile.defines_int.in
-rm -f lib/Makefile.am
-rm -f configure.in
-rm -f includes/stamp-*
-rm -f includes/silcconfig.*
-rm -f includes/version_internal.h
-rm -f includes/silcdefs.h.in
-rm -f Makefile.in
-rm -f doc/draft-*.txt
-rm -f doc/Makefile.in
-rm -f includes/Makefile.in
-rm -f lib/Makefile.in
-rm -f lib/contrib/Makefile.in
-rm -f lib/silcclient/Makefile.in
-rm -f lib/silccore/Makefile.in
-rm -f lib/silcutil/Makefile.in
-rm -f lib/silccrypt/Makefile.in
-rm -f lib/silcmath/Makefile.in
-rm -f lib/silcsim/Makefile.in
-rm -f lib/silcsim/modules/Makefile.in
-rm -f lib/silcske/Makefile.in
-rm -rf lib/silcmath/gmp/.deps
-rm -f silcd/Makefile.in silcd/log* silcd/*.log
-rm -f silc/Makefile.in silc/log* silc/*.log
-rm -f aclocal.m4
-rm -f config.status
-rm -f configure
-cd irssi
-rm -f COPYING
-rm -f INSTALL
-rm -f Makefile.in
-rm -f */Makefile.in
-rm -f */*/Makefile.in
-rm -f */*/*/Makefile.in
-rm -f */*/*/*/Makefile.in
-rm -f default-theme.h
-rm -f libtool-shared
-rm -f stamp-*
-rm -f docs/startup*.txt
-cd docs/help
-cp Makefile.am.gen ..
-rm -f * 2>/dev/null
-mv ../Makefile.am.gen .
-cd ../..
-rm -f docs/help/in/Makefile.am
-echo "Done."
index 3bf1cccb335fa04c4535a4b9a1693f6f953d5c8a..57bb940018db6a6450f29c73ab17856235d984f0 100755 (executable)
@@ -100,8 +100,8 @@ if [ "$TYPE" = "HTML" ]; then
 
   # Generate index template from the DIRECTORY files. The template for
   # the generated index template is INDEX.tmpl.
-  files=`find $SRC -name "DIRECTORY"`
-  for i in $files
+  dfiles=`find $SRC -name "DIRECTORY"`
+  for i in $dfiles
   do
     # Get library name
     name=`grep "@LIBRARY=" $i |cut -d=  -f2`
@@ -177,8 +177,7 @@ if [ "$TYPE" = "HTML" ]; then
   done
 
   # Generate the index and TOC files from the DIRECTORY files
-  files=`find $SRC -name "DIRECTORY"`
-  for i in $files
+  for i in $dfiles
   do
     # Get library name
     name=`grep "@LIBRARY=" $i |cut -d=  -f2`
index 10163ef81abd84d4a19da91f0f8114f8041789fe..f4ced5f18c9aead30b9117b1d37bbfa0be9421bc 100644 (file)
@@ -167,6 +167,7 @@ static void
 silc_channel_message(SilcClient client, SilcClientConnection conn,
                     SilcClientEntry sender, SilcChannelEntry channel,
                     SilcMessagePayload payload,
+                    SilcChannelPrivateKey key,
                     SilcMessageFlags flags, const unsigned char *message,
                     SilcUInt32 message_len)
 {
index 79a93467cd9797a6b909331d9d208c111baadd3f..632c2990f94c880e285de6fc97da3534cfec23a6 100644 (file)
@@ -62,6 +62,12 @@ RB_Generate_Documentation (
 
       RB_Say ("generating documentation for \"%s\"\n", cur_header->name);
 
+#if 1
+     /* If MAIN_HEADER, do not create file */
+     if (cur_header->type == MAIN_HEADER)
+       continue;
+#endif
+
       if (output_mode == HTML)
         {
           sprintf(fname, "%s-%s.html", doc_base, cur_header->function_name);
index 822bafd501e40fda2773fb916b541c6fe252d505..6462608958e71b7d1aaa34723e9479c4a66b9e6c 100644 (file)
-;
-; Exports file for SILC Core DLL.
-;
-; This file is generated from MinGW compiled object files using the
-; following command:
-;
-; dlltool --export-all --output-def libsilc.def libsilc.a
-;
-; ----------------------------------------------------------------------------
-;
-; If you edit this file by adding or removing any exports be sure to
-; preserve the ordinal values (the @ n in the exports) and add new exports
-; always at the end of the list with new ordinal value. Do not ever
-; add new export with old ordinal value if you need to preserve backwards
-; compatiblity. -Pekka
-;
-EXPORTS
-       silc_aes_context_len @ 235 ;
-       silc_aes_decrypt_cbc @ 236 ;
-       silc_aes_encrypt_cbc @ 237 ;
-       silc_aes_set_key @ 238 ;
-       silc_aes_set_key_with_string @ 239 ;
-       silc_argument_get_arg_num @ 240 ;
-       silc_argument_get_arg_type @ 241 ;
-       silc_argument_get_first_arg @ 242 ;
-       silc_argument_get_next_arg @ 243 ;
-       silc_argument_payload_encode @ 244 ;
-       silc_argument_payload_encode_payload @ 245 ;
-       silc_argument_payload_free @ 246 ;
-       silc_argument_payload_parse @ 247 ;
-       silc_auth_get_data @ 248 ;
-       silc_auth_get_method @ 249 ;
-       silc_auth_payload_encode @ 250 ;
-       silc_auth_payload_free @ 251 ;
-       silc_auth_payload_parse @ 252 ;
-       silc_auth_public_key_auth_generate @ 253 ;
-       silc_auth_public_key_auth_verify @ 254 ;
-       silc_auth_public_key_auth_verify_data @ 255 ;
-       silc_auth_verify @ 256 ;
-       silc_auth_verify_data @ 257 ;
-       silc_blowfish_context_len @ 258 ;
-       silc_blowfish_decrypt_cbc @ 259 ;
-       silc_blowfish_encrypt_cbc @ 260 ;
-       silc_blowfish_set_key @ 261 ;
-       silc_blowfish_set_key_with_string @ 262 ;
-       silc_buffer_format @ 263 ;
-       silc_buffer_unformat @ 264 ;
-       silc_calloc @ 265 ;
-       silc_cast_context_len @ 266 ;
-       silc_cast_decrypt_cbc @ 267 ;
-       silc_cast_encrypt_cbc @ 268 ;
-       silc_cast_set_key @ 269 ;
-       silc_cast_set_key_with_string @ 270 ;
-       silc_channel_get_id @ 271 ;
-       silc_channel_get_id_parse @ 272 ;
-       silc_channel_get_mode @ 273 ;
-       silc_channel_get_name @ 274 ;
-       silc_channel_key_get_cipher @ 275 ;
-       silc_channel_key_get_id @ 276 ;
-       silc_channel_key_get_key @ 277 ;
-       silc_channel_key_payload_encode @ 278 ;
-       silc_channel_key_payload_free @ 279 ;
-       silc_channel_key_payload_parse @ 280 ;
-       silc_channel_payload_encode @ 289 ;
-       silc_channel_payload_free @ 290 ;
-       silc_channel_payload_list_free @ 291 ;
-       silc_channel_payload_parse @ 292 ;
-       silc_channel_payload_parse_list @ 293 ;
-       silc_check_line @ 294 ;
-       silc_cipher_alloc @ 295 ;
-       silc_cipher_decrypt @ 296 ;
-       silc_cipher_encrypt @ 297 ;
-       silc_cipher_free @ 298 ;
-       silc_cipher_get_block_len @ 299 ;
-       silc_cipher_get_iv @ 300 ;
-       silc_cipher_get_key_len @ 301 ;
-       silc_cipher_get_supported @ 302 ;
-       silc_cipher_is_supported @ 303 ;
-       silc_cipher_list @ 304 ;
-       silc_cipher_register @ 305 ;
-       silc_cipher_register_default @ 306 ;
-       silc_cipher_set_iv @ 307 ;
-       silc_cipher_set_key @ 308 ;
-       silc_cipher_unregister @ 309 ;
-       silc_client_chmode @ 310 ;
-       silc_client_chumode @ 311 ;
-       silc_client_chumode_char @ 312 ;
-       silc_command_get @ 313 ;
-       silc_command_get_args @ 314 ;
-       silc_command_get_ident @ 315 ;
-       silc_command_payload_encode @ 316 ;
-       silc_command_payload_encode_payload @ 317 ;
-       silc_command_payload_encode_va @ 318 ;
-       silc_command_payload_encode_vap @ 319 ;
-       silc_command_payload_free @ 320 ;
-       silc_command_payload_parse @ 321 ;
-       silc_command_reply_payload_encode_va @ 322 ;
-       silc_command_set_command @ 323 ;
-       silc_command_set_ident @ 324 ;
-       silc_config_open @ 327 ;
-       silc_debug @ 328 DATA ;
-       silc_pem_decode @ 329 ;
-       silc_default_ciphers @ 330 DATA ;
-       silc_default_hash @ 331 DATA ;
-       silc_default_hmacs @ 332 DATA ;
-       silc_default_pkcs @ 333 DATA ;
-       silc_pem_encode @ 334 ;
-       silc_pem_encode_file @ 335 ;
-       silc_file_readfile @ 336 ;
-       silc_file_writefile @ 337 ;
-       silc_file_writefile_mode @ 338 ;
-       silc_format @ 339 ;
-       silc_free @ 340 ;
-       silc_get_time @ 341 ;
-       silc_gets @ 342 ;
-       silc_gettimeofday @ 343 ;
-       silc_hash_alloc @ 344 ;
-       silc_hash_client_id_compare @ 345 ;
-       silc_hash_data @ 346 ;
-       silc_hash_data_compare @ 347 ;
-       silc_hash_fingerprint @ 348 ;
-       silc_hash_free @ 349 ;
-       silc_hash_get_supported @ 350 ;
-       silc_hash_id @ 351 ;
-       silc_hash_id_compare @ 352 ;
-       silc_hash_is_supported @ 353 ;
-       silc_hash_len @ 354 ;
-       silc_hash_list @ 355 ;
-       silc_hash_make @ 356 ;
-       silc_hash_ptr @ 357 ;
-       silc_hash_register @ 358 ;
-       silc_hash_register_default @ 359 ;
-       silc_hash_string @ 360 ;
-       silc_hash_string_compare @ 361 ;
-       silc_hash_table_add @ 362 ;
-       silc_hash_table_add_ext @ 363 ;
-       silc_hash_table_alloc @ 364 ;
-       silc_hash_table_count @ 365 ;
-       silc_hash_table_del @ 366 ;
-       silc_hash_table_del_by_context @ 367 ;
-       silc_hash_table_del_by_context_ext @ 368 ;
-       silc_hash_table_del_ext @ 369 ;
-       silc_hash_table_find @ 370 ;
-       silc_hash_table_find_ext @ 371 ;
-       silc_hash_table_find_foreach @ 372 ;
-       silc_hash_table_find_foreach_ext @ 373 ;
-       silc_hash_table_foreach @ 374 ;
-       silc_hash_table_free @ 375 ;
-       silc_hash_table_get @ 376 ;
-       silc_hash_table_list @ 377 ;
-       silc_hash_table_rehash @ 378 ;
-       silc_hash_table_rehash_ext @ 379 ;
-       silc_hash_table_replace @ 380 ;
-       silc_hash_table_replace_ext @ 381 ;
-       silc_hash_table_size @ 382 ;
-       silc_hash_uint @ 383 ;
-       silc_hash_unregister @ 384 ;
-       silc_hmac_alloc @ 385 ;
-       silc_hmac_free @ 386 ;
-       silc_hmac_get_supported @ 387 ;
-       silc_hmac_is_supported @ 388 ;
-       silc_hmac_len @ 389 ;
-       silc_hmac_list @ 390 ;
-       silc_hmac_make @ 391 ;
-       silc_hmac_make_truncated @ 393 ;
-       silc_hmac_make_with_key @ 394 ;
-       silc_hmac_register @ 395 ;
-       silc_hmac_register_default @ 396 ;
-       silc_hmac_set_key @ 397 ;
-       silc_hmac_unregister @ 398 ;
-       silc_id_dup @ 399 ;
-       silc_id_get_len @ 400 ;
-       silc_id_id2str @ 401 ;
-       silc_id_payload_encode @ 402 ;
-       silc_id_payload_free @ 403 ;
-       silc_id_payload_get_data @ 404 ;
-       silc_id_payload_get_id @ 405 ;
-       silc_id_payload_get_len @ 406 ;
-       silc_id_payload_get_type @ 407 ;
-       silc_id_payload_parse @ 408 ;
-       silc_id_payload_parse_id @ 410 ;
-       silc_id_render @ 411 ;
-       silc_id_str2id @ 412 ;
-       silc_idcache_add @ 413 ;
-       silc_idcache_alloc @ 414 ;
-       silc_idcache_del @ 415 ;
-       silc_idcache_del_all @ 416 ;
-       silc_idcache_del_by_context @ 417 ;
-       silc_idcache_del_by_id @ 418 ;
-       silc_idcache_del_by_id_ext @ 419 ;
-       silc_idcache_find_by_context @ 420 ;
-       silc_idcache_find_by_id @ 421 ;
-       silc_idcache_find_by_id_one @ 422 ;
-       silc_idcache_find_by_id_one_ext @ 423 ;
-       silc_idcache_find_by_name @ 424 ;
-       silc_idcache_find_by_name_one @ 425 ;
-       silc_idcache_free @ 426 ;
-       silc_idcache_get_all @ 427 ;
-       silc_idcache_list_count @ 428 ;
-       silc_idcache_list_first @ 429 ;
-       silc_idcache_list_free @ 430 ;
-       silc_idcache_list_next @ 431 ;
-       silc_idcache_purge @ 432 ;
-       silc_idcache_purge_by_context @ 433 ;
-       silc_key_agreement_get_hostname @ 434 ;
-       silc_key_agreement_get_port @ 435 ;
-       silc_key_agreement_payload_encode @ 436 ;
-       silc_key_agreement_payload_free @ 437 ;
-       silc_key_agreement_payload_parse @ 438 ;
-       silc_log_output @ 439 ;
-       silc_log_output_debug @ 440 ;
-       silc_log_output_hexdump @ 441 ;
-       silc_log_reset_callbacks @ 442 ;
-       silc_log_reset_debug_callbacks @ 443 ;
-       silc_log_set_callback @ 444 ;
-       silc_log_set_debug_callbacks @ 445 ;
-       silc_log_set_file @ 446 ;
-       silc_malloc @ 448 ;
-       silc_math_gen_prime @ 454 ;
-       silc_math_prime_test @ 455 ;
-       silc_md5_context_len @ 456 ;
-       silc_md5_final @ 457 ;
-       silc_md5_init @ 458 ;
-       silc_md5_transform @ 459 ;
-       silc_md5_update @ 460 ;
-       silc_mp_abs @ 461 ;
-       silc_mp_add @ 462 ;
-       silc_mp_add_ui @ 463 ;
-       silc_mp_and @ 464 ;
-       silc_mp_bin2mp @ 465 ;
-       silc_mp_cmp @ 466 ;
-       silc_mp_cmp_si @ 467 ;
-       silc_mp_cmp_ui @ 468 ;
-       silc_mp_div @ 469 ;
-       silc_mp_div_2exp @ 470 ;
-       silc_mp_div_2exp_qr @ 471 ;
-       silc_mp_div_qr @ 472 ;
-       silc_mp_div_ui @ 473 ;
-       silc_mp_gcd @ 474 ;
-       silc_mp_gcdext @ 475 ;
-       silc_mp_get_str @ 476 ;
-       silc_mp_get_ui @ 477 ;
-       silc_mp_init @ 478 ;
-       silc_mp_mod @ 479 ;
-       silc_mp_mod_2exp @ 480 ;
-       silc_mp_mod_ui @ 481 ;
-       silc_mp_modinv @ 482 ;
-       silc_mp_mp2bin @ 483 ;
-       silc_mp_mp2bin_noalloc @ 484 ;
-       silc_mp_mul @ 485 ;
-       silc_mp_mul_2exp @ 486 ;
-       silc_mp_mul_ui @ 487 ;
-       silc_mp_neg @ 488 ;
-       silc_mp_or @ 489 ;
-       silc_mp_pow @ 490 ;
-       silc_mp_pow_mod @ 491 ;
-       silc_mp_pow_mod_ui @ 492 ;
-       silc_mp_pow_ui @ 493 ;
-       silc_mp_set @ 494 ;
-       silc_mp_set_si @ 495 ;
-       silc_mp_set_str @ 496 ;
-       silc_mp_set_ui @ 497 ;
-       silc_mp_size @ 498 ;
-       silc_mp_sizeinbase @ 499 ;
-       silc_mp_sqrt @ 500 ;
-       silc_mp_sub @ 501 ;
-       silc_mp_sub_ui @ 502 ;
-       silc_mp_uninit @ 503 ;
-       silc_mp_xor @ 504 ;
-       silc_mutex_alloc @ 505 ;
-       silc_mutex_free @ 506 ;
-       silc_mutex_lock @ 507 ;
-       silc_mutex_unlock @ 508 ;
-       silc_net_accept_connection @ 509 ;
-       silc_net_addr2bin @ 510 ;
-       silc_net_check_host_by_sock @ 511 ;
-       silc_net_check_local_by_sock @ 512 ;
-       silc_net_close_connection @ 513 ;
-       silc_net_close_server @ 514 ;
-       silc_net_create_connection @ 515 ;
-       silc_net_create_connection_async @ 516 ;
-       silc_net_create_server @ 517 ;
-       silc_net_get_local_port @ 518 ;
-       silc_net_get_remote_port @ 519 ;
-       silc_net_get_socket_opt @ 520 ;
-       silc_net_is_ip @ 521 ;
-       silc_net_localhost @ 522 ;
-       silc_net_set_socket_nonblock @ 523 ;
-       silc_net_set_socket_opt @ 524 ;
-       silc_net_win32_init @ 525 ;
-       silc_net_win32_uninit @ 526 ;
-       silc_none_context_len @ 527 ;
-       silc_none_decrypt_cbc @ 528 ;
-       silc_none_encrypt_cbc @ 529 ;
-       silc_none_set_key @ 530 ;
-       silc_none_set_key_with_string @ 531 ;
-       silc_notify_get_arg_num @ 532 ;
-       silc_notify_get_args @ 533 ;
-       silc_notify_get_type @ 534 ;
-       silc_notify_payload_encode @ 535 ;
-       silc_notify_payload_encode_args @ 536 ;
-       silc_notify_payload_free @ 537 ;
-       silc_notify_payload_parse @ 538 ;
-       silc_packet_assemble @ 539 ;
-       silc_packet_context_alloc @ 540 ;
-       silc_packet_context_dup @ 541 ;
-       silc_packet_context_free @ 542 ;
-       silc_packet_encrypt @ 544 ;
-       silc_packet_parse @ 545 ;
-       silc_packet_parse_special @ 546 ;
-       silc_packet_receive @ 547 ;
-       silc_packet_receive_process @ 548 ;
-       silc_packet_send @ 549 ;
-       silc_packet_send_prepare @ 550 ;
-       silc_parse_command_line @ 551 ;
-       silc_parse_userfqdn @ 552 ;
-       silc_pkcs1_decrypt @ 553 ;
-       silc_pkcs1_encrypt @ 554 ;
-       silc_pkcs1_sign @ 555 ;
-       silc_pkcs1_verify @ 556 ;
-       silc_pkcs_alloc @ 557 ;
-       silc_pkcs_decode_identifier @ 558 ;
-       silc_pkcs_decrypt @ 559 ;
-       silc_pkcs_encode_identifier @ 560 ;
-       silc_pkcs_encrypt @ 561 ;
-       silc_pkcs_free @ 562 ;
-       silc_pkcs_free_identifier @ 563 ;
-       silc_pkcs_get_key_len @ 564 ;
-       silc_pkcs_get_private_key @ 565 ;
-       silc_pkcs_get_public_key @ 566 ;
-       silc_pkcs_get_supported @ 567 ;
-       silc_pkcs_is_supported @ 568 ;
-       silc_pkcs_list @ 569 ;
-       silc_pkcs_load_private_key @ 570 ;
-       silc_pkcs_load_public_key @ 571 ;
-       silc_pkcs_private_key_alloc @ 572 ;
-       silc_pkcs_private_key_data_encode @ 573 ;
-       silc_pkcs_private_key_data_set @ 574 ;
-       silc_pkcs_private_key_decode @ 575 ;
-       silc_pkcs_private_key_encode @ 576 ;
-       silc_pkcs_private_key_free @ 577 ;
-       silc_pkcs_private_key_set @ 578 ;
-       silc_pkcs_public_key_alloc @ 579 ;
-       silc_pkcs_public_key_data_encode @ 580 ;
-       silc_pkcs_public_key_data_set @ 581 ;
-       silc_pkcs_public_key_decode @ 582 ;
-       silc_pkcs_public_key_encode @ 583 ;
-       silc_pkcs_public_key_free @ 584 ;
-       silc_pkcs_public_key_set @ 585 ;
-       silc_pkcs_register @ 586 ;
-       silc_pkcs_register_default @ 587 ;
-       silc_pkcs_save_private_key @ 588 ;
-       silc_pkcs_save_public_key @ 590 ;
-       silc_pkcs_save_public_key_data @ 591 ;
-       silc_pkcs_sign @ 592 ;
-       silc_pkcs_sign_with_hash @ 593 ;
-       silc_pkcs_unregister @ 594 ;
-       silc_pkcs_verify @ 595 ;
-       silc_pkcs_verify_with_hash @ 596 ;
-       silc_protocol_alloc @ 602 ;
-       silc_protocol_cancel @ 603 ;
-       silc_protocol_execute @ 604 ;
-       silc_protocol_execute_final @ 605 ;
-       silc_protocol_free @ 606 ;
-       silc_protocol_list @ 607 ;
-       silc_protocol_register @ 608 ;
-       silc_protocol_unregister @ 609 ;
-       silc_rc5_context_len @ 610 ;
-       silc_rc5_decrypt_cbc @ 611 ;
-       silc_rc5_encrypt_cbc @ 612 ;
-       silc_rc5_set_key @ 613 ;
-       silc_rc5_set_key_with_string @ 614 ;
-       silc_rc6_context_len @ 615 ;
-       silc_rc6_decrypt_cbc @ 616 ;
-       silc_rc6_encrypt_cbc @ 617 ;
-       silc_rc6_set_key @ 618 ;
-       silc_rc6_set_key_with_string @ 619 ;
-       silc_realloc @ 620 ;
-       silc_rng_add_noise @ 621 ;
-       silc_rng_alloc @ 622 ;
-       silc_rng_free @ 623 ;
-       silc_rng_get_byte @ 624 ;
-       silc_rng_get_rn16 @ 625 ;
-       silc_rng_get_rn32 @ 626 ;
-       silc_rng_get_rn_data @ 627 ;
-       silc_rng_get_rn_string @ 628 ;
-       silc_rng_global_add_noise @ 629 ;
-       silc_rng_global_get_byte @ 630 ;
-       silc_rng_global_get_rn16 @ 631 ;
-       silc_rng_global_get_rn32 @ 632 ;
-       silc_rng_global_get_rn_data @ 633 ;
-       silc_rng_global_get_rn_string @ 634 ;
-       silc_rng_global_init @ 635 ;
-       silc_rng_global_uninit @ 636 ;
-       silc_rng_init @ 637 ;
-       silc_rsa_clear_keys @ 638 ;
-       silc_rsa_context_len @ 639 ;
-       silc_rsa_decrypt @ 640 ;
-       silc_rsa_encrypt @ 641 ;
-       silc_rsa_get_private_key @ 642 ;
-       silc_rsa_get_public_key @ 643 ;
-       silc_rsa_init @ 644 ;
-       silc_rsa_set_private_key @ 645 ;
-       silc_rsa_set_public_key @ 646 ;
-       silc_rsa_sign @ 647 ;
-       silc_rsa_verify @ 648 ;
-       silc_schedule @ 649 ;
-       silc_schedule_init @ 650 ;
-       silc_schedule_one @ 651 ;
-       silc_schedule_set_listen_fd @ 652 ;
-       silc_schedule_stop @ 653 ;
-       silc_schedule_task_add @ 654 ;
-       silc_schedule_task_del @ 655 ;
-       silc_schedule_task_del_by_callback @ 656 ;
-       silc_schedule_task_del_by_context @ 657 ;
-       silc_schedule_task_del_by_fd @ 658 ;
-       silc_schedule_uninit @ 659 ;
-       silc_schedule_unset_listen_fd @ 660 ;
-       silc_schedule_wakeup @ 661 ;
-       silc_select @ 665 ;
-       silc_sha1_context_len @ 666 ;
-       silc_sha1_final @ 667 ;
-       silc_sha1_init @ 668 ;
-       silc_sha1_transform @ 669 ;
-       silc_sha1_update @ 670 ;
-       silc_ske_abort @ 671 ;
-       silc_ske_alloc @ 672 ;
-       silc_ske_assemble_security_properties @ 673 ;
-       silc_ske_end @ 675 ;
-       silc_ske_free @ 676 ;
-       silc_ske_free_key_material @ 677 ;
-       silc_ske_group_get_by_name @ 678 ;
-       silc_ske_group_get_by_number @ 679 ;
-       silc_ske_get_supported_groups @ 680 ;
-       silc_ske_group_get_number @ 681 ;
-       silc_ske_groups @ 682 ;
-       silc_ske_initiator_finish @ 683 ;
-       silc_ske_initiator_phase_1 @ 684 ;
-       silc_ske_initiator_phase_2 @ 685 ;
-       silc_ske_initiator_start @ 686 ;
-       silc_ske_payload_ke_decode @ 688 ;
-       silc_ske_payload_ke_encode @ 689 ;
-       silc_ske_payload_ke_free @ 690 ;
-       silc_ske_payload_start_decode @ 691 ;
-       silc_ske_payload_start_encode @ 692 ;
-       silc_ske_payload_start_free @ 693 ;
-       silc_ske_process_key_material @ 694 ;
-       silc_ske_process_key_material_data @ 695 ;
-       silc_ske_responder_finish @ 696 ;
-       silc_ske_responder_phase_1 @ 697 ;
-       silc_ske_responder_phase_2 @ 698 ;
-       silc_ske_responder_start @ 699 ;
-       silc_ske_select_security_properties @ 700 ;
-       silc_ske_set_callbacks @ 701 ;
-       silc_socket_alloc @ 702 ;
-       silc_socket_dup @ 703 ;
-       silc_socket_free @ 704 ;
-       silc_socket_host_lookup @ 705 ;
-       silc_socket_read @ 706 ;
-       silc_socket_set_heartbeat @ 707 ;
-       silc_socket_write @ 708 ;
-       silc_string_compare @ 709 ;
-       silc_thread_create @ 710 ;
-       silc_thread_exit @ 711 ;
-       silc_thread_self @ 712 ;
-       silc_thread_wait @ 713 ;
-       silc_to_upper @ 715 ;
-       silc_twofish_context_len @ 716 ;
-       silc_twofish_decrypt_cbc @ 717 ;
-       silc_twofish_encrypt_cbc @ 718 ;
-       silc_twofish_set_key @ 719 ;
-       silc_twofish_set_key_with_string @ 720 ;
-       silc_buffer_format_vp @ 789 ;
-       silc_buffer_unformat_vp @ 790 ;
-       silc_sftp_client_start @ 791 ;
-       silc_sftp_client_shutdown @ 792 ;
-       silc_sftp_client_receive_process @ 793 ;
-       silc_sftp_open @ 794 ;
-       silc_sftp_close @ 795 ;
-       silc_sftp_read @ 796 ;
-       silc_sftp_write @ 797 ;
-       silc_sftp_remove @ 798 ;
-       silc_sftp_rename @ 799 ;
-       silc_sftp_mkdir @ 800 ;
-       silc_sftp_rmdir @ 801 ;
-       silc_sftp_opendir @ 802 ;
-       silc_sftp_readdir @ 803 ;
-       silc_sftp_stat @ 804 ;
-       silc_sftp_lstat @ 805 ;
-       silc_sftp_fstat @ 806 ;
-       silc_sftp_setstat @ 807 ;
-       silc_sftp_fsetstat @ 808 ;
-       silc_sftp_readlink @ 809 ;
-       silc_sftp_symlink @ 810 ;
-       silc_sftp_realpath @ 811 ;
-       silc_sftp_extended @ 812 ;
-       silc_sftp_server_start @ 813 ;
-       silc_sftp_server_shutdown @ 814 ;
-       silc_sftp_server_receive_process @ 815 ;
-       silc_sftp_fs_memory @ 816 ;
-       silc_sftp_fs_memory_alloc @ 817 ;
-       silc_sftp_fs_memory_free @ 818 ;
-       silc_sftp_fs_memory_add_dir @ 819 ;
-       silc_sftp_fs_memory_del_dir @ 820 ;
-       silc_sftp_fs_memory_add_file @ 821 ;
-       silc_sftp_fs_memory_del_file @ 822 ;
-       silc_file_open @ 824 ;
-       silc_file_close @ 825 ;
-       silc_file_read @ 826 ;
-       silc_file_write @ 827 ;
-       silc_file_size @ 828 ;
-       silc_hmac_init @ 829 ;
-       silc_hmac_update @ 830 ;
-       silc_hmac_final @ 831 ;
-       silc_hmac_init_with_key @ 832 ;
-       silc_hmac_get_name @ 833 ;
-       silc_hmac_get_hash @ 834 ;
-       silc_net_localip @ 835 ;
-       silc_sftp_server_set_monitor @ 836 ;
-       silc_net_gethostbyname @ 837 ;
-       silc_net_gethostbyaddr @ 838 ;
-       silc_net_gethostbyname_async @ 839 ;
-       silc_net_gethostbyaddr_async @ 840 ;
-       silc_net_is_ip4 @ 841 ;
-       silc_net_is_ip6 @ 842 ;
-       silc_log_set_debug_string @ 843 ;
-       silc_log_reset_all @ 844 ;
-       silc_log_flush_all @ 845 ;
-       silc_log_get_file @ 846 ;
-       silc_log_quick @ 847 DATA ;
-       silc_log_flushdelay @ 848 DATA ;
-       silc_hash_table_list_reset @ 849 ;
-       silc_debug_hexdump @ 850 DATA ;
-       silc_memdup @ 851 ;
-       silc_command_get_status @ 852 ;
-       silc_utf8_encode @ 853 ;
-       silc_utf8_decode @ 854 ;
-       silc_utf8_encoded_len @ 855 ;
-       silc_utf8_valid @ 856 ;
-       silc_mime_parse @ 857 ;
-       silc_get_status_message @ 858 ;
-       silc_get_mode_list @ 859 ;
-       silc_hash_table_find_by_context @ 860 ;
-       silc_string_is_ascii @ 862 ;
-       silc_parse_version_string @ 863 ;
-       silc_version_to_num @ 864 ;
-       silc_fingerprint @ 865 ;
-        silc_get_packet_name @ 866 ;
-        silc_get_command_name @ 867 ;
-        silc_strncat @ 868 ;
-        silc_attribute_payload_parse @ 869 ;
-        silc_attribute_payload_encode @ 870 ;
-        silc_attribute_payload_alloc @ 871 ;
-        silc_attribute_payload_free @ 872 ;
-        silc_attribute_payload_list_free @ 873 ;
-        silc_attribute_payload_encode_data @ 874 ;
-        silc_attribute_get_attribute @ 875 ;
-        silc_attribute_get_data @ 876 ;
-        silc_attribute_get_object @ 877 ;
-        silc_attribute_get_flags @ 878 ;
-        silc_attribute_get_verify_data @ 879 ;
-        silc_hash_get_name @ 880 ;
-       silc_create_key_pair @ 881 ;
-       silc_load_key_pair @ 882 ;
-       silc_show_public_key @ 883 ;
-       silc_change_private_key_passphrase @ 884 ;
-       silc_argument_payload_encode_one @ 885 ;
-       silc_message_payload_decrypt @ 886 ;
-       silc_message_payload_parse @ 887 ;
-       silc_message_payload_encrypt @ 888 ;
-       silc_message_payload_encode @ 889 ;
-       silc_message_payload_free @ 890 ;
-       silc_message_get_flags @ 891 ;
-       silc_message_get_data @ 892 ;
-       silc_message_get_mac @ 893 ;
-       silc_message_get_iv @ 894 ;
-       silc_message_signed_payload_parse @ 895 ;
-       silc_message_signed_payload_encode @ 896 ;
-       silc_message_signed_payload_free @ 897 ;
-       silc_message_signed_verify @ 898 ;
-        silc_message_signed_get_public_key @ 899 ;
-        silc_hmac_unregister_all @ 900 ;
-        silc_hash_unregister_all @ 901 ;
-        silc_pkcs_unregister_all @ 902 ;
-        silc_cipher_unregister_all @ 903 ;
-        silc_rng_get_byte_fast @ 904 ;
-        silc_cipher_get_name @ 905 ;
-        silc_pkcs_public_key_payload_encode @ 908 ;
-        silc_pkcs_public_key_payload_decode @ 909 ;
-       silc_auth_get_public_data @ 910 ;
-       silc_auth_public_key_auth_generate_wpub @ 911 ;
-       silc_status_get_args @ 912 ;
-
+;\r
+; Exports file for SILC Core DLL.\r
+;\r
+; This file is generated from MinGW compiled object files using the\r
+; following command:\r
+;\r
+; dlltool --export-all --output-def libsilc.def libsilc.a\r
+;\r
+; ----------------------------------------------------------------------------\r
+;\r
+; If you edit this file by adding or removing any exports be sure to\r
+; preserve the ordinal values (the @ n in the exports) and add new exports\r
+; always at the end of the list with new ordinal value. Do not ever\r
+; add new export with old ordinal value if you need to preserve backwards\r
+; compatiblity. -Pekka\r
+;\r
+EXPORTS\r
+       silc_aes_context_len @ 235 ;\r
+       silc_aes_decrypt_cbc @ 236 ;\r
+       silc_aes_encrypt_cbc @ 237 ;\r
+       silc_aes_set_key @ 238 ;\r
+       silc_aes_set_key_with_string @ 239 ;\r
+       silc_argument_get_arg_num @ 240 ;\r
+       silc_argument_get_arg_type @ 241 ;\r
+       silc_argument_get_first_arg @ 242 ;\r
+       silc_argument_get_next_arg @ 243 ;\r
+       silc_argument_payload_encode @ 244 ;\r
+       silc_argument_payload_encode_payload @ 245 ;\r
+       silc_argument_payload_free @ 246 ;\r
+       silc_argument_payload_parse @ 247 ;\r
+       silc_auth_get_data @ 248 ;\r
+       silc_auth_get_method @ 249 ;\r
+       silc_auth_payload_encode @ 250 ;\r
+       silc_auth_payload_free @ 251 ;\r
+       silc_auth_payload_parse @ 252 ;\r
+       silc_auth_public_key_auth_generate @ 253 ;\r
+       silc_auth_public_key_auth_verify @ 254 ;\r
+       silc_auth_public_key_auth_verify_data @ 255 ;\r
+       silc_auth_verify @ 256 ;\r
+       silc_auth_verify_data @ 257 ;\r
+       silc_blowfish_context_len @ 258 ;\r
+       silc_blowfish_decrypt_cbc @ 259 ;\r
+       silc_blowfish_encrypt_cbc @ 260 ;\r
+       silc_blowfish_set_key @ 261 ;\r
+       silc_blowfish_set_key_with_string @ 262 ;\r
+       silc_buffer_format @ 263 ;\r
+       silc_buffer_unformat @ 264 ;\r
+       silc_calloc @ 265 ;\r
+       silc_cast_context_len @ 266 ;\r
+       silc_cast_decrypt_cbc @ 267 ;\r
+       silc_cast_encrypt_cbc @ 268 ;\r
+       silc_cast_set_key @ 269 ;\r
+       silc_cast_set_key_with_string @ 270 ;\r
+       silc_channel_get_id @ 271 ;\r
+       silc_channel_get_id_parse @ 272 ;\r
+       silc_channel_get_mode @ 273 ;\r
+       silc_channel_get_name @ 274 ;\r
+       silc_channel_key_get_cipher @ 275 ;\r
+       silc_channel_key_get_id @ 276 ;\r
+       silc_channel_key_get_key @ 277 ;\r
+       silc_channel_key_payload_encode @ 278 ;\r
+       silc_channel_key_payload_free @ 279 ;\r
+       silc_channel_key_payload_parse @ 280 ;\r
+       silc_channel_payload_encode @ 289 ;\r
+       silc_channel_payload_free @ 290 ;\r
+       silc_channel_payload_list_free @ 291 ;\r
+       silc_channel_payload_parse @ 292 ;\r
+       silc_channel_payload_parse_list @ 293 ;\r
+       silc_check_line @ 294 ;\r
+       silc_cipher_alloc @ 295 ;\r
+       silc_cipher_decrypt @ 296 ;\r
+       silc_cipher_encrypt @ 297 ;\r
+       silc_cipher_free @ 298 ;\r
+       silc_cipher_get_block_len @ 299 ;\r
+       silc_cipher_get_iv @ 300 ;\r
+       silc_cipher_get_key_len @ 301 ;\r
+       silc_cipher_get_supported @ 302 ;\r
+       silc_cipher_is_supported @ 303 ;\r
+       silc_cipher_list @ 304 ;\r
+       silc_cipher_register @ 305 ;\r
+       silc_cipher_register_default @ 306 ;\r
+       silc_cipher_set_iv @ 307 ;\r
+       silc_cipher_set_key @ 308 ;\r
+       silc_cipher_unregister @ 309 ;\r
+       silc_client_chmode @ 310 ;\r
+       silc_client_chumode @ 311 ;\r
+       silc_client_chumode_char @ 312 ;\r
+       silc_command_get @ 313 ;\r
+       silc_command_get_args @ 314 ;\r
+       silc_command_get_ident @ 315 ;\r
+       silc_command_payload_encode @ 316 ;\r
+       silc_command_payload_encode_payload @ 317 ;\r
+       silc_command_payload_encode_va @ 318 ;\r
+       silc_command_payload_encode_vap @ 319 ;\r
+       silc_command_payload_free @ 320 ;\r
+       silc_command_payload_parse @ 321 ;\r
+       silc_command_reply_payload_encode_va @ 322 ;\r
+       silc_command_set_command @ 323 ;\r
+       silc_command_set_ident @ 324 ;\r
+       silc_config_open @ 327 ;\r
+       silc_debug @ 328 DATA ;\r
+       silc_pem_decode @ 329 ;\r
+       silc_default_ciphers @ 330 DATA ;\r
+       silc_default_hash @ 331 DATA ;\r
+       silc_default_hmacs @ 332 DATA ;\r
+       silc_default_pkcs @ 333 DATA ;\r
+       silc_pem_encode @ 334 ;\r
+       silc_pem_encode_file @ 335 ;\r
+       silc_file_readfile @ 336 ;\r
+       silc_file_writefile @ 337 ;\r
+       silc_file_writefile_mode @ 338 ;\r
+       silc_format @ 339 ;\r
+       silc_free @ 340 ;\r
+       silc_get_time @ 341 ;\r
+       silc_gets @ 342 ;\r
+       silc_gettimeofday @ 343 ;\r
+       silc_hash_alloc @ 344 ;\r
+       silc_hash_client_id_compare @ 345 ;\r
+       silc_hash_data @ 346 ;\r
+       silc_hash_data_compare @ 347 ;\r
+       silc_hash_fingerprint @ 348 ;\r
+       silc_hash_free @ 349 ;\r
+       silc_hash_get_supported @ 350 ;\r
+       silc_hash_id @ 351 ;\r
+       silc_hash_id_compare @ 352 ;\r
+       silc_hash_is_supported @ 353 ;\r
+       silc_hash_len @ 354 ;\r
+       silc_hash_list @ 355 ;\r
+       silc_hash_make @ 356 ;\r
+       silc_hash_ptr @ 357 ;\r
+       silc_hash_register @ 358 ;\r
+       silc_hash_register_default @ 359 ;\r
+       silc_hash_string @ 360 ;\r
+       silc_hash_string_compare @ 361 ;\r
+       silc_hash_table_add @ 362 ;\r
+       silc_hash_table_add_ext @ 363 ;\r
+       silc_hash_table_alloc @ 364 ;\r
+       silc_hash_table_count @ 365 ;\r
+       silc_hash_table_del @ 366 ;\r
+       silc_hash_table_del_by_context @ 367 ;\r
+       silc_hash_table_del_by_context_ext @ 368 ;\r
+       silc_hash_table_del_ext @ 369 ;\r
+       silc_hash_table_find @ 370 ;\r
+       silc_hash_table_find_ext @ 371 ;\r
+       silc_hash_table_find_foreach @ 372 ;\r
+       silc_hash_table_find_foreach_ext @ 373 ;\r
+       silc_hash_table_foreach @ 374 ;\r
+       silc_hash_table_free @ 375 ;\r
+       silc_hash_table_get @ 376 ;\r
+       silc_hash_table_list @ 377 ;\r
+       silc_hash_table_rehash @ 378 ;\r
+       silc_hash_table_rehash_ext @ 379 ;\r
+       silc_hash_table_replace @ 380 ;\r
+       silc_hash_table_replace_ext @ 381 ;\r
+       silc_hash_table_size @ 382 ;\r
+       silc_hash_uint @ 383 ;\r
+       silc_hash_unregister @ 384 ;\r
+       silc_hmac_alloc @ 385 ;\r
+       silc_hmac_free @ 386 ;\r
+       silc_hmac_get_supported @ 387 ;\r
+       silc_hmac_is_supported @ 388 ;\r
+       silc_hmac_len @ 389 ;\r
+       silc_hmac_list @ 390 ;\r
+       silc_hmac_make @ 391 ;\r
+       silc_hmac_make_truncated @ 393 ;\r
+       silc_hmac_make_with_key @ 394 ;\r
+       silc_hmac_register @ 395 ;\r
+       silc_hmac_register_default @ 396 ;\r
+       silc_hmac_set_key @ 397 ;\r
+       silc_hmac_unregister @ 398 ;\r
+       silc_id_dup @ 399 ;\r
+       silc_id_get_len @ 400 ;\r
+       silc_id_id2str @ 401 ;\r
+       silc_id_payload_encode @ 402 ;\r
+       silc_id_payload_free @ 403 ;\r
+       silc_id_payload_get_data @ 404 ;\r
+       silc_id_payload_get_id @ 405 ;\r
+       silc_id_payload_get_len @ 406 ;\r
+       silc_id_payload_get_type @ 407 ;\r
+       silc_id_payload_parse @ 408 ;\r
+       silc_id_payload_parse_id @ 410 ;\r
+       silc_id_render @ 411 ;\r
+       silc_id_str2id @ 412 ;\r
+       silc_idcache_add @ 413 ;\r
+       silc_idcache_alloc @ 414 ;\r
+       silc_idcache_del @ 415 ;\r
+       silc_idcache_del_all @ 416 ;\r
+       silc_idcache_del_by_context @ 417 ;\r
+       silc_idcache_del_by_id @ 418 ;\r
+       silc_idcache_del_by_id_ext @ 419 ;\r
+       silc_idcache_find_by_context @ 420 ;\r
+       silc_idcache_find_by_id @ 421 ;\r
+       silc_idcache_find_by_id_one @ 422 ;\r
+       silc_idcache_find_by_id_one_ext @ 423 ;\r
+       silc_idcache_find_by_name @ 424 ;\r
+       silc_idcache_find_by_name_one @ 425 ;\r
+       silc_idcache_free @ 426 ;\r
+       silc_idcache_get_all @ 427 ;\r
+       silc_idcache_list_count @ 428 ;\r
+       silc_idcache_list_first @ 429 ;\r
+       silc_idcache_list_free @ 430 ;\r
+       silc_idcache_list_next @ 431 ;\r
+       silc_idcache_purge @ 432 ;\r
+       silc_idcache_purge_by_context @ 433 ;\r
+       silc_key_agreement_get_hostname @ 434 ;\r
+       silc_key_agreement_get_port @ 435 ;\r
+       silc_key_agreement_payload_encode @ 436 ;\r
+       silc_key_agreement_payload_free @ 437 ;\r
+       silc_key_agreement_payload_parse @ 438 ;\r
+       silc_log_output @ 439 ;\r
+       silc_log_output_debug @ 440 ;\r
+       silc_log_output_hexdump @ 441 ;\r
+       silc_log_reset_callbacks @ 442 ;\r
+       silc_log_reset_debug_callbacks @ 443 ;\r
+       silc_log_set_callback @ 444 ;\r
+       silc_log_set_debug_callbacks @ 445 ;\r
+       silc_log_set_file @ 446 ;\r
+       silc_malloc @ 448 ;\r
+       silc_math_gen_prime @ 454 ;\r
+       silc_math_prime_test @ 455 ;\r
+       silc_md5_context_len @ 456 ;\r
+       silc_md5_final @ 457 ;\r
+       silc_md5_init @ 458 ;\r
+       silc_md5_transform @ 459 ;\r
+       silc_md5_update @ 460 ;\r
+       silc_mp_abs @ 461 ;\r
+       silc_mp_add @ 462 ;\r
+       silc_mp_add_ui @ 463 ;\r
+       silc_mp_and @ 464 ;\r
+       silc_mp_bin2mp @ 465 ;\r
+       silc_mp_cmp @ 466 ;\r
+       silc_mp_cmp_si @ 467 ;\r
+       silc_mp_cmp_ui @ 468 ;\r
+       silc_mp_div @ 469 ;\r
+       silc_mp_div_2exp @ 470 ;\r
+       silc_mp_div_2exp_qr @ 471 ;\r
+       silc_mp_div_qr @ 472 ;\r
+       silc_mp_div_ui @ 473 ;\r
+       silc_mp_gcd @ 474 ;\r
+       silc_mp_gcdext @ 475 ;\r
+       silc_mp_get_str @ 476 ;\r
+       silc_mp_get_ui @ 477 ;\r
+       silc_mp_init @ 478 ;\r
+       silc_mp_mod @ 479 ;\r
+       silc_mp_mod_2exp @ 480 ;\r
+       silc_mp_mod_ui @ 481 ;\r
+       silc_mp_modinv @ 482 ;\r
+       silc_mp_mp2bin @ 483 ;\r
+       silc_mp_mp2bin_noalloc @ 484 ;\r
+       silc_mp_mul @ 485 ;\r
+       silc_mp_mul_2exp @ 486 ;\r
+       silc_mp_mul_ui @ 487 ;\r
+       silc_mp_neg @ 488 ;\r
+       silc_mp_or @ 489 ;\r
+       silc_mp_pow @ 490 ;\r
+       silc_mp_pow_mod @ 491 ;\r
+       silc_mp_pow_mod_ui @ 492 ;\r
+       silc_mp_pow_ui @ 493 ;\r
+       silc_mp_set @ 494 ;\r
+       silc_mp_set_si @ 495 ;\r
+       silc_mp_set_str @ 496 ;\r
+       silc_mp_set_ui @ 497 ;\r
+       silc_mp_size @ 498 ;\r
+       silc_mp_sizeinbase @ 499 ;\r
+       silc_mp_sqrt @ 500 ;\r
+       silc_mp_sub @ 501 ;\r
+       silc_mp_sub_ui @ 502 ;\r
+       silc_mp_uninit @ 503 ;\r
+       silc_mp_xor @ 504 ;\r
+       silc_mutex_alloc @ 505 ;\r
+       silc_mutex_free @ 506 ;\r
+       silc_mutex_lock @ 507 ;\r
+       silc_mutex_unlock @ 508 ;\r
+       silc_net_accept_connection @ 509 ;\r
+       silc_net_addr2bin @ 510 ;\r
+       silc_net_check_host_by_sock @ 511 ;\r
+       silc_net_check_local_by_sock @ 512 ;\r
+       silc_net_close_connection @ 513 ;\r
+       silc_net_close_server @ 514 ;\r
+       silc_net_create_connection @ 515 ;\r
+       silc_net_create_connection_async @ 516 ;\r
+       silc_net_create_server @ 517 ;\r
+       silc_net_get_local_port @ 518 ;\r
+       silc_net_get_remote_port @ 519 ;\r
+       silc_net_get_socket_opt @ 520 ;\r
+       silc_net_is_ip @ 521 ;\r
+       silc_net_localhost @ 522 ;\r
+       silc_net_set_socket_nonblock @ 523 ;\r
+       silc_net_set_socket_opt @ 524 ;\r
+       silc_net_win32_init @ 525 ;\r
+       silc_net_win32_uninit @ 526 ;\r
+       silc_none_context_len @ 527 ;\r
+       silc_none_decrypt_cbc @ 528 ;\r
+       silc_none_encrypt_cbc @ 529 ;\r
+       silc_none_set_key @ 530 ;\r
+       silc_none_set_key_with_string @ 531 ;\r
+       silc_notify_get_arg_num @ 532 ;\r
+       silc_notify_get_args @ 533 ;\r
+       silc_notify_get_type @ 534 ;\r
+       silc_notify_payload_encode @ 535 ;\r
+       silc_notify_payload_encode_args @ 536 ;\r
+       silc_notify_payload_free @ 537 ;\r
+       silc_notify_payload_parse @ 538 ;\r
+       silc_packet_assemble @ 539 ;\r
+       silc_packet_context_alloc @ 540 ;\r
+       silc_packet_context_dup @ 541 ;\r
+       silc_packet_context_free @ 542 ;\r
+       silc_packet_encrypt @ 544 ;\r
+       silc_packet_parse @ 545 ;\r
+       silc_packet_parse_special @ 546 ;\r
+       silc_packet_receive @ 547 ;\r
+       silc_packet_receive_process @ 548 ;\r
+       silc_packet_send @ 549 ;\r
+       silc_packet_send_prepare @ 550 ;\r
+       silc_parse_command_line @ 551 ;\r
+       silc_parse_userfqdn @ 552 ;\r
+       silc_pkcs1_decrypt @ 553 ;\r
+       silc_pkcs1_encrypt @ 554 ;\r
+       silc_pkcs1_sign @ 555 ;\r
+       silc_pkcs1_verify @ 556 ;\r
+       silc_pkcs_alloc @ 557 ;\r
+       silc_pkcs_decode_identifier @ 558 ;\r
+       silc_pkcs_decrypt @ 559 ;\r
+       silc_pkcs_encode_identifier @ 560 ;\r
+       silc_pkcs_encrypt @ 561 ;\r
+       silc_pkcs_free @ 562 ;\r
+       silc_pkcs_free_identifier @ 563 ;\r
+       silc_pkcs_get_key_len @ 564 ;\r
+       silc_pkcs_get_private_key @ 565 ;\r
+       silc_pkcs_get_public_key @ 566 ;\r
+       silc_pkcs_get_supported @ 567 ;\r
+       silc_pkcs_is_supported @ 568 ;\r
+       silc_pkcs_list @ 569 ;\r
+       silc_pkcs_load_private_key @ 570 ;\r
+       silc_pkcs_load_public_key @ 571 ;\r
+       silc_pkcs_private_key_alloc @ 572 ;\r
+       silc_pkcs_private_key_data_encode @ 573 ;\r
+       silc_pkcs_private_key_data_set @ 574 ;\r
+       silc_pkcs_private_key_decode @ 575 ;\r
+       silc_pkcs_private_key_encode @ 576 ;\r
+       silc_pkcs_private_key_free @ 577 ;\r
+       silc_pkcs_private_key_set @ 578 ;\r
+       silc_pkcs_public_key_alloc @ 579 ;\r
+       silc_pkcs_public_key_data_encode @ 580 ;\r
+       silc_pkcs_public_key_data_set @ 581 ;\r
+       silc_pkcs_public_key_decode @ 582 ;\r
+       silc_pkcs_public_key_encode @ 583 ;\r
+       silc_pkcs_public_key_free @ 584 ;\r
+       silc_pkcs_public_key_set @ 585 ;\r
+       silc_pkcs_register @ 586 ;\r
+       silc_pkcs_register_default @ 587 ;\r
+       silc_pkcs_save_private_key @ 588 ;\r
+       silc_pkcs_save_public_key @ 590 ;\r
+       silc_pkcs_save_public_key_data @ 591 ;\r
+       silc_pkcs_sign @ 592 ;\r
+       silc_pkcs_sign_with_hash @ 593 ;\r
+       silc_pkcs_unregister @ 594 ;\r
+       silc_pkcs_verify @ 595 ;\r
+       silc_pkcs_verify_with_hash @ 596 ;\r
+       silc_protocol_alloc @ 602 ;\r
+       silc_protocol_cancel @ 603 ;\r
+       silc_protocol_execute @ 604 ;\r
+       silc_protocol_execute_final @ 605 ;\r
+       silc_protocol_free @ 606 ;\r
+       silc_protocol_list @ 607 ;\r
+       silc_protocol_register @ 608 ;\r
+       silc_protocol_unregister @ 609 ;\r
+       silc_rc5_context_len @ 610 ;\r
+       silc_rc5_decrypt_cbc @ 611 ;\r
+       silc_rc5_encrypt_cbc @ 612 ;\r
+       silc_rc5_set_key @ 613 ;\r
+       silc_rc5_set_key_with_string @ 614 ;\r
+       silc_realloc @ 620 ;\r
+       silc_rng_add_noise @ 621 ;\r
+       silc_rng_alloc @ 622 ;\r
+       silc_rng_free @ 623 ;\r
+       silc_rng_get_byte @ 624 ;\r
+       silc_rng_get_rn16 @ 625 ;\r
+       silc_rng_get_rn32 @ 626 ;\r
+       silc_rng_get_rn_data @ 627 ;\r
+       silc_rng_get_rn_string @ 628 ;\r
+       silc_rng_global_add_noise @ 629 ;\r
+       silc_rng_global_get_byte @ 630 ;\r
+       silc_rng_global_get_rn16 @ 631 ;\r
+       silc_rng_global_get_rn32 @ 632 ;\r
+       silc_rng_global_get_rn_data @ 633 ;\r
+       silc_rng_global_get_rn_string @ 634 ;\r
+       silc_rng_global_init @ 635 ;\r
+       silc_rng_global_uninit @ 636 ;\r
+       silc_rng_init @ 637 ;\r
+       silc_rsa_clear_keys @ 638 ;\r
+       silc_rsa_context_len @ 639 ;\r
+       silc_rsa_decrypt @ 640 ;\r
+       silc_rsa_encrypt @ 641 ;\r
+       silc_rsa_get_private_key @ 642 ;\r
+       silc_rsa_get_public_key @ 643 ;\r
+       silc_rsa_init @ 644 ;\r
+       silc_rsa_set_private_key @ 645 ;\r
+       silc_rsa_set_public_key @ 646 ;\r
+       silc_rsa_sign @ 647 ;\r
+       silc_rsa_verify @ 648 ;\r
+       silc_schedule @ 649 ;\r
+       silc_schedule_init @ 650 ;\r
+       silc_schedule_one @ 651 ;\r
+       silc_schedule_set_listen_fd @ 652 ;\r
+       silc_schedule_stop @ 653 ;\r
+       silc_schedule_task_add @ 654 ;\r
+       silc_schedule_task_del @ 655 ;\r
+       silc_schedule_task_del_by_callback @ 656 ;\r
+       silc_schedule_task_del_by_context @ 657 ;\r
+       silc_schedule_task_del_by_fd @ 658 ;\r
+       silc_schedule_uninit @ 659 ;\r
+       silc_schedule_unset_listen_fd @ 660 ;\r
+       silc_schedule_wakeup @ 661 ;\r
+       silc_select @ 665 ;\r
+       silc_sha1_context_len @ 666 ;\r
+       silc_sha1_final @ 667 ;\r
+       silc_sha1_init @ 668 ;\r
+       silc_sha1_transform @ 669 ;\r
+       silc_sha1_update @ 670 ;\r
+       silc_ske_abort @ 671 ;\r
+       silc_ske_alloc @ 672 ;\r
+       silc_ske_assemble_security_properties @ 673 ;\r
+       silc_ske_end @ 675 ;\r
+       silc_ske_free @ 676 ;\r
+       silc_ske_free_key_material @ 677 ;\r
+       silc_ske_group_get_by_name @ 678 ;\r
+       silc_ske_group_get_by_number @ 679 ;\r
+       silc_ske_get_supported_groups @ 680 ;\r
+       silc_ske_group_get_number @ 681 ;\r
+       silc_ske_groups @ 682 ;\r
+       silc_ske_initiator_finish @ 683 ;\r
+       silc_ske_initiator_phase_1 @ 684 ;\r
+       silc_ske_initiator_phase_2 @ 685 ;\r
+       silc_ske_initiator_start @ 686 ;\r
+       silc_ske_payload_ke_decode @ 688 ;\r
+       silc_ske_payload_ke_encode @ 689 ;\r
+       silc_ske_payload_ke_free @ 690 ;\r
+       silc_ske_payload_start_decode @ 691 ;\r
+       silc_ske_payload_start_encode @ 692 ;\r
+       silc_ske_payload_start_free @ 693 ;\r
+       silc_ske_process_key_material @ 694 ;\r
+       silc_ske_process_key_material_data @ 695 ;\r
+       silc_ske_responder_finish @ 696 ;\r
+       silc_ske_responder_phase_1 @ 697 ;\r
+       silc_ske_responder_phase_2 @ 698 ;\r
+       silc_ske_responder_start @ 699 ;\r
+       silc_ske_select_security_properties @ 700 ;\r
+       silc_ske_set_callbacks @ 701 ;\r
+       silc_socket_alloc @ 702 ;\r
+       silc_socket_dup @ 703 ;\r
+       silc_socket_free @ 704 ;\r
+       silc_socket_host_lookup @ 705 ;\r
+       silc_socket_read @ 706 ;\r
+       silc_socket_set_heartbeat @ 707 ;\r
+       silc_socket_write @ 708 ;\r
+       silc_string_compare @ 709 ;\r
+       silc_thread_create @ 710 ;\r
+       silc_thread_exit @ 711 ;\r
+       silc_thread_self @ 712 ;\r
+       silc_thread_wait @ 713 ;\r
+       silc_to_upper @ 715 ;\r
+       silc_twofish_context_len @ 716 ;\r
+       silc_twofish_decrypt_cbc @ 717 ;\r
+       silc_twofish_encrypt_cbc @ 718 ;\r
+       silc_twofish_set_key @ 719 ;\r
+       silc_twofish_set_key_with_string @ 720 ;\r
+       silc_buffer_format_vp @ 789 ;\r
+       silc_buffer_unformat_vp @ 790 ;\r
+       silc_sftp_client_start @ 791 ;\r
+       silc_sftp_client_shutdown @ 792 ;\r
+       silc_sftp_client_receive_process @ 793 ;\r
+       silc_sftp_open @ 794 ;\r
+       silc_sftp_close @ 795 ;\r
+       silc_sftp_read @ 796 ;\r
+       silc_sftp_write @ 797 ;\r
+       silc_sftp_remove @ 798 ;\r
+       silc_sftp_rename @ 799 ;\r
+       silc_sftp_mkdir @ 800 ;\r
+       silc_sftp_rmdir @ 801 ;\r
+       silc_sftp_opendir @ 802 ;\r
+       silc_sftp_readdir @ 803 ;\r
+       silc_sftp_stat @ 804 ;\r
+       silc_sftp_lstat @ 805 ;\r
+       silc_sftp_fstat @ 806 ;\r
+       silc_sftp_setstat @ 807 ;\r
+       silc_sftp_fsetstat @ 808 ;\r
+       silc_sftp_readlink @ 809 ;\r
+       silc_sftp_symlink @ 810 ;\r
+       silc_sftp_realpath @ 811 ;\r
+       silc_sftp_extended @ 812 ;\r
+       silc_sftp_server_start @ 813 ;\r
+       silc_sftp_server_shutdown @ 814 ;\r
+       silc_sftp_server_receive_process @ 815 ;\r
+       silc_sftp_fs_memory @ 816 ;\r
+       silc_sftp_fs_memory_alloc @ 817 ;\r
+       silc_sftp_fs_memory_free @ 818 ;\r
+       silc_sftp_fs_memory_add_dir @ 819 ;\r
+       silc_sftp_fs_memory_del_dir @ 820 ;\r
+       silc_sftp_fs_memory_add_file @ 821 ;\r
+       silc_sftp_fs_memory_del_file @ 822 ;\r
+       silc_file_open @ 824 ;\r
+       silc_file_close @ 825 ;\r
+       silc_file_read @ 826 ;\r
+       silc_file_write @ 827 ;\r
+       silc_file_size @ 828 ;\r
+       silc_hmac_init @ 829 ;\r
+       silc_hmac_update @ 830 ;\r
+       silc_hmac_final @ 831 ;\r
+       silc_hmac_init_with_key @ 832 ;\r
+       silc_hmac_get_name @ 833 ;\r
+       silc_hmac_get_hash @ 834 ;\r
+       silc_net_localip @ 835 ;\r
+       silc_sftp_server_set_monitor @ 836 ;\r
+       silc_net_gethostbyname @ 837 ;\r
+       silc_net_gethostbyaddr @ 838 ;\r
+       silc_net_gethostbyname_async @ 839 ;\r
+       silc_net_gethostbyaddr_async @ 840 ;\r
+       silc_net_is_ip4 @ 841 ;\r
+       silc_net_is_ip6 @ 842 ;\r
+       silc_log_set_debug_string @ 843 ;\r
+       silc_log_reset_all @ 844 ;\r
+       silc_log_flush_all @ 845 ;\r
+       silc_log_get_file @ 846 ;\r
+       silc_log_quick @ 847 DATA ;\r
+       silc_log_flushdelay @ 848 DATA ;\r
+       silc_hash_table_list_reset @ 849 ;\r
+       silc_debug_hexdump @ 850 DATA ;\r
+       silc_memdup @ 851 ;\r
+       silc_command_get_status @ 852 ;\r
+       silc_utf8_encode @ 853 ;\r
+       silc_utf8_decode @ 854 ;\r
+       silc_utf8_encoded_len @ 855 ;\r
+       silc_utf8_valid @ 856 ;\r
+       silc_mime_parse @ 857 ;\r
+       silc_get_status_message @ 858 ;\r
+       silc_get_mode_list @ 859 ;\r
+       silc_hash_table_find_by_context @ 860 ;\r
+       silc_string_is_ascii @ 862 ;\r
+       silc_parse_version_string @ 863 ;\r
+       silc_version_to_num @ 864 ;\r
+       silc_fingerprint @ 865 ;\r
+        silc_get_packet_name @ 866 ;\r
+        silc_get_command_name @ 867 ;\r
+        silc_strncat @ 868 ;\r
+        silc_attribute_payload_parse @ 869 ;\r
+        silc_attribute_payload_encode @ 870 ;\r
+        silc_attribute_payload_alloc @ 871 ;\r
+        silc_attribute_payload_free @ 872 ;\r
+        silc_attribute_payload_list_free @ 873 ;\r
+        silc_attribute_payload_encode_data @ 874 ;\r
+        silc_attribute_get_attribute @ 875 ;\r
+        silc_attribute_get_data @ 876 ;\r
+        silc_attribute_get_object @ 877 ;\r
+        silc_attribute_get_flags @ 878 ;\r
+        silc_attribute_get_verify_data @ 879 ;\r
+        silc_hash_get_name @ 880 ;\r
+       silc_create_key_pair @ 881 ;\r
+       silc_load_key_pair @ 882 ;\r
+       silc_show_public_key @ 883 ;\r
+       silc_change_private_key_passphrase @ 884 ;\r
+       silc_argument_payload_encode_one @ 885 ;\r
+       silc_message_payload_decrypt @ 886 ;\r
+       silc_message_payload_parse @ 887 ;\r
+       silc_message_payload_encrypt @ 888 ;\r
+       silc_message_payload_encode @ 889 ;\r
+       silc_message_payload_free @ 890 ;\r
+       silc_message_get_flags @ 891 ;\r
+       silc_message_get_data @ 892 ;\r
+       silc_message_get_mac @ 893 ;\r
+       silc_message_get_iv @ 894 ;\r
+       silc_message_signed_payload_parse @ 895 ;\r
+       silc_message_signed_payload_encode @ 896 ;\r
+       silc_message_signed_payload_free @ 897 ;\r
+       silc_message_signed_verify @ 898 ;\r
+        silc_message_signed_get_public_key @ 899 ;\r
+        silc_hmac_unregister_all @ 900 ;\r
+        silc_hash_unregister_all @ 901 ;\r
+        silc_pkcs_unregister_all @ 902 ;\r
+        silc_cipher_unregister_all @ 903 ;\r
+        silc_rng_get_byte_fast @ 904 ;\r
+        silc_cipher_get_name @ 905 ;\r
+        silc_pkcs_public_key_payload_encode @ 908 ;\r
+        silc_pkcs_public_key_payload_decode @ 909 ;\r
+       silc_auth_get_public_data @ 910 ;\r
+       silc_auth_public_key_auth_generate_wpub @ 911 ;\r
+       silc_status_get_args @ 912 ;\r
+       silc_vcard_encode @ 913 ;\r
+       silc_vcard_decode @ 914 ;\r
+       silc_vcard_alloc @ 915 ;\r
+       silc_vcard_free @ 916 ;\r
+       silc_vcard_fprintf @ 917 ;\r
+       silc_hash_babbleprint @ 918 ;\r
+       silc_get_real_name @ 919 ;\r
+       silc_get_username @ 920 ;\r
+       silc_utf8_strcasecmp @ 921 ;\r
+       silc_utf8_strncasecmp @ 922 ;\r
+       silc_stringprep @ 923;\r
+       silc_identifier_check @ 924 ;\r
+       silc_identifier_verify @ 925 ;\r
index 83ea65b4c0815aaab9a81d94b841009e7ba14251..fcc2d87f55de8a06fb5e74b4781088216fe12ad0 100644 (file)
@@ -43,8 +43,7 @@ RSC=rc.exe
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILC_EXPORTS" /YX /FD /c\r
-# ADD CPP /nologo /MT /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILC_EXPORTS" /D "MP_API_COMPATIBLE" /D "DLL" /FD /c\r
-# SUBTRACT CPP /YX\r
+# ADD CPP /nologo /MT /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILC_EXPORTS" /D "MP_API_COMPATIBLE" /D "DLL" /D "HAVE_SILCDEFS_H" /FD /Zm300 /c\r
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
 # ADD BASE RSC /l 0x409 /d "NDEBUG"\r
@@ -71,12 +70,11 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILC_EXPORTS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /MTd /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILC_EXPORTS" /D "MP_API_COMPATIBLE" /D "SILC_DEBUG" /D "DLL" /FD /GZ /c\r
-# SUBTRACT CPP /YX\r
+# ADD CPP /nologo /MTd /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "_DEBUG" /D "SILC_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILC_EXPORTS" /D "MP_API_COMPATIBLE" /D "DLL" /D "HAVE_SILCDEFS_H" /FD /GZ /Zm300 /c\r
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
 # ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# ADD RSC /l 0x409 /d "_DEBUG"\r
+# ADD RSC /l 0x409 /d "_DEBUG" /Zm300\r
 BSC32=bscmake.exe\r
 # ADD BASE BSC32 /nologo\r
 # ADD BSC32 /nologo\r
@@ -137,6 +135,10 @@ SOURCE=..\..\lib\silccore\silcnotify.c
 \r
 SOURCE=..\..\lib\silccore\silcpacket.c\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\silccore\silcstatus.c\r
+# End Source File\r
 # End Group\r
 # Begin Group "silcske"\r
 \r
@@ -171,6 +173,10 @@ SOURCE=..\..\lib\silcutil\silcconfig.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silcutil\silcfileutil.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silcutil\silchashtable.c\r
 # End Source File\r
 # Begin Source File\r
@@ -199,10 +205,18 @@ SOURCE=..\..\lib\silcutil\silcsockconn.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silcutil\silcstringprep.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silcutil\silcstrutil.c\r
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silcutil\silcutf8.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silcutil\silcutil.c\r
 # End Source File\r
 # Begin Source File\r
@@ -295,18 +309,10 @@ SOURCE=..\..\lib\silccrypt\none.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\pkcs1.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rc5.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\rc6.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rsa.c\r
 # End Source File\r
 # Begin Source File\r
@@ -331,6 +337,10 @@ SOURCE=..\..\lib\silccrypt\silcpkcs.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silccrypt\silcpkcs1.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silccrypt\silcrng.c\r
 # End Source File\r
 # Begin Source File\r
@@ -358,6 +368,22 @@ SOURCE=..\..\lib\silcsftp\sftp_server.c
 SOURCE=..\..\lib\silcsftp\sftp_util.c\r
 # End Source File\r
 # End Group\r
+# Begin Group "contrib"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\contrib\nfkc.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\contrib\rfc3454.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\contrib\stringprep.c\r
+# End Source File\r
+# End Group\r
 # End Group\r
 # Begin Group "Header Files"\r
 \r
@@ -409,6 +435,10 @@ SOURCE=..\..\lib\silccore\silcnotify.h
 \r
 SOURCE=..\..\lib\silccore\silcprivate.h\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\silccore\silcstatus.h\r
+# End Source File\r
 # End Group\r
 # Begin Group "silcske No. 1"\r
 \r
@@ -463,10 +493,6 @@ SOURCE=..\..\lib\silcutil\silcdlist.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcutil\silcfileutil.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silcutil\silchashtable.h\r
 # End Source File\r
 # Begin Source File\r
@@ -507,6 +533,10 @@ SOURCE=..\..\lib\silcutil\silcsockconn.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silcutil\silcstringprep.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silcutil\silcthread.h\r
 # End Source File\r
 # Begin Source File\r
@@ -515,6 +545,10 @@ SOURCE=..\..\lib\silcutil\silctypes.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silcutil\silcutf8.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silcutil\silcutil.h\r
 # End Source File\r
 # Begin Source File\r
@@ -615,10 +649,6 @@ SOURCE=..\..\lib\silccrypt\none.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\pkcs1.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rc5.h\r
 # End Source File\r
 # Begin Source File\r
@@ -627,14 +657,6 @@ SOURCE=..\..\lib\silccrypt\rc5_internal.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\rc6.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silccrypt\rc6_internal.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rijndael_internal.h\r
 # End Source File\r
 # Begin Source File\r
@@ -675,6 +697,10 @@ SOURCE=..\..\lib\silccrypt\silcpkcs.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silccrypt\silcpkcs1.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silccrypt\silcrng.h\r
 # End Source File\r
 # Begin Source File\r
@@ -702,6 +728,22 @@ SOURCE=..\..\lib\silcsftp\silcsftp.h
 SOURCE=..\..\lib\silcsftp\silcsftp_fs.h\r
 # End Source File\r
 # End Group\r
+# Begin Group "contrib No. 1"\r
+\r
+# PROP Default_Filter ""\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\contrib\gunicomp.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\contrib\gunidecomp.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\contrib\stringprep.h\r
+# End Source File\r
+# End Group\r
 # End Group\r
 # Begin Group "Resource Files"\r
 \r
index 2ca90cd5edf8e58eb0d4800318e36f5503dda134..4e28dc8e32779b62d8b57bcabeda5d25f05b1638 100644 (file)
@@ -41,7 +41,7 @@ RSC=rc.exe
 # PROP Intermediate_Dir "Release"\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
-# ADD CPP /nologo /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /YX /FD /c\r
+# ADD CPP /nologo /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /D "HAVE_SILCDEFS_H" /YX /FD /Zm300 /c\r
 # ADD BASE RSC /l 0x409 /d "NDEBUG"\r
 # ADD RSC /l 0x409 /d "NDEBUG"\r
 BSC32=bscmake.exe\r
@@ -64,7 +64,7 @@ LIB32=link.exe -lib
 # PROP Intermediate_Dir "Debug"\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
-# ADD CPP /nologo /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /D "HAVE_SILCDEFS_H" /YX /FD /GZ /c\r
 # SUBTRACT CPP /WX\r
 # ADD BASE RSC /l 0x409 /d "_DEBUG"\r
 # ADD RSC /l 0x409 /d "_DEBUG"\r
@@ -127,6 +127,10 @@ SOURCE=..\..\lib\silccore\silcnotify.c
 \r
 SOURCE=..\..\lib\silccore\silcpacket.c\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\silccore\silcstatus.c\r
+# End Source File\r
 # End Group\r
 # Begin Group "silcske"\r
 \r
@@ -285,18 +289,10 @@ SOURCE=..\..\lib\silccrypt\none.c
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\pkcs1.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rc5.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\rc6.c\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rsa.c\r
 # End Source File\r
 # Begin Source File\r
@@ -321,6 +317,10 @@ SOURCE=..\..\lib\silccrypt\silcpkcs.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=..\..\lib\silccrypt\silcpkcs1.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=..\..\lib\silccrypt\silcrng.c\r
 # End Source File\r
 # Begin Source File\r
@@ -605,10 +605,6 @@ SOURCE=..\..\lib\silccrypt\none.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\pkcs1.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rc5.h\r
 # End Source File\r
 # Begin Source File\r
@@ -617,14 +613,6 @@ SOURCE=..\..\lib\silccrypt\rc5_internal.h
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silccrypt\rc6.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silccrypt\rc6_internal.h\r
-# End Source File\r
-# Begin Source File\r
-\r
 SOURCE=..\..\lib\silccrypt\rijndael_internal.h\r
 # End Source File\r
 # Begin Source File\r
index b9c751bda1bc42cc05d87e2c4ac4611937269eea..73c2643b19b8960545522cba2c7cb3598c29f799 100644 (file)
-;\r
-; Exports file for SILC Client DLL.\r
-;\r
-; This file is generated from MinGW compiled object files using the\r
-; following command:\r
-;\r
-; dlltool --export-all --output-def libsilc.def libsilc.a\r
-;\r
-; ----------------------------------------------------------------------------\r
-;\r
-; If you edit this file by adding or removing any exports be sure to\r
-; preserve the ordinal values (the @ n in the exports) and add new exports\r
-; always at the end of the list with new ordinal value. Do not ever\r
-; add new export with old ordinal value if you need to preserve backwards\r
-; compatiblity. -Pekka\r
-;\r
-EXPORTS\r
-       silc_ske_check_version @ 1 ;\r
-       silc_client_add_channel_private_key @ 2 ;\r
-       silc_client_add_connection @ 3 ;\r
-       silc_client_add_private_message_key @ 4 ;\r
-       silc_client_add_private_message_key_ske @ 5 ;\r
-       silc_client_add_socket @ 6 ;\r
-       silc_client_alloc @ 7 ;\r
-       silc_client_channel_message @ 8 ;\r
-       silc_client_close_connection @ 9 ;\r
-       silc_client_command_alloc @ 10 ;\r
-       silc_client_command_ban @ 11 ;\r
-       silc_client_command_close @ 12 ;\r
-       silc_client_command_cmode @ 13 ;\r
-       silc_client_command_connect @ 14 ;\r
-       silc_client_command_cumode @ 15 ;\r
-       silc_client_command_dup @ 16 ;\r
-       silc_client_command_find @ 17 ;\r
-       silc_client_command_free @ 18 ;\r
-       silc_client_command_get_channel_by_id_callback @ 19 ;\r
-       silc_client_command_get_client_by_id_callback @ 20 ;\r
-       silc_client_command_get_client_callback @ 21 ;\r
-       silc_client_command_get_clients_list_callback @ 22 ;\r
-       silc_client_command_getkey @ 23 ;\r
-       silc_client_command_identify @ 24 ;\r
-       silc_client_command_info @ 25 ;\r
-       silc_client_command_invite @ 26 ;\r
-       silc_client_command_join @ 27 ;\r
-       silc_client_command_kick @ 28 ;\r
-       silc_client_command_kill @ 29 ;\r
-       silc_client_command_leave @ 30 ;\r
-       silc_client_command_list @ 31 ;\r
-       silc_client_command_motd @ 32 ;\r
-       silc_client_command_nick @ 33 ;\r
-       silc_client_command_oper @ 34 ;\r
-       silc_client_command_pending @ 35 ;\r
-       silc_client_command_pending_check @ 36 ;\r
-       silc_client_command_pending_del @ 37 ;\r
-       silc_client_command_ping @ 38 ;\r
-       silc_client_command_quit @ 39 ;\r
-       silc_client_command_reply_ban @ 40 ;\r
-       silc_client_command_reply_close @ 41 ;\r
-       silc_client_command_reply_cmode @ 42 ;\r
-       silc_client_command_reply_connect @ 43 ;\r
-       silc_client_command_reply_cumode @ 44 ;\r
-       silc_client_command_reply_free @ 45 ;\r
-       silc_client_command_reply_getkey @ 46 ;\r
-       silc_client_command_reply_identify @ 47 ;\r
-       silc_client_command_reply_info @ 48 ;\r
-       silc_client_command_reply_invite @ 49 ;\r
-       silc_client_command_reply_join @ 50 ;\r
-       silc_client_command_reply_kick @ 51 ;\r
-       silc_client_command_reply_kill @ 52 ;\r
-       silc_client_command_reply_leave @ 53 ;\r
-       silc_client_command_reply_list @ 54 ;\r
-       silc_client_command_reply_motd @ 55 ;\r
-       silc_client_command_reply_nick @ 56 ;\r
-       silc_client_command_reply_oper @ 57 ;\r
-       silc_client_command_reply_ping @ 58 ;\r
-       silc_client_command_reply_process @ 59 ;\r
-       silc_client_command_reply_shutdown @ 60 ;\r
-       silc_client_command_reply_silcoper @ 61 ;\r
-       silc_client_command_reply_topic @ 62 ;\r
-       silc_client_command_reply_umode @ 63 ;\r
-       silc_client_command_reply_users @ 64 ;\r
-       silc_client_command_reply_whois @ 65 ;\r
-       silc_client_command_reply_whowas @ 66 ;\r
-       silc_client_command_shutdown @ 67 ;\r
-       silc_client_command_silcoper @ 68 ;\r
-       silc_client_command_topic @ 70 ;\r
-       silc_client_command_umode @ 71 ;\r
-       silc_client_command_users @ 72 ;\r
-       silc_client_command_whois @ 73 ;\r
-       silc_client_command_whowas @ 74 ;\r
-       silc_client_connect_to_server @ 75 ;\r
-       silc_client_del_channel @ 76 ;\r
-       silc_client_del_channel_private_key @ 77 ;\r
-       silc_client_del_channel_private_keys @ 78 ;\r
-       silc_client_del_client @ 79 ;\r
-       silc_client_del_client_entry @ 80 ;\r
-       silc_client_del_connection @ 81 ;\r
-       silc_client_del_private_message_key @ 82 ;\r
-       silc_client_del_server @ 83 ;\r
-       silc_client_del_socket @ 84 ;\r
-       silc_client_disconnected_by_server @ 85 ;\r
-       silc_client_error_by_server @ 86 ;\r
-       silc_client_free @ 87 ;\r
-       silc_client_free_channel_private_keys @ 88 ;\r
-       silc_client_free_private_message_keys @ 89 ;\r
-       silc_client_get_channel @ 90 ;\r
-       silc_client_get_channel_by_id @ 91 ;\r
-       silc_client_get_channel_by_id_resolve @ 92 ;\r
-       silc_client_get_client_by_id @ 93 ;\r
-       silc_client_get_client_by_id_resolve @ 94 ;\r
-       silc_client_get_clients @ 95 ;\r
-       silc_client_get_clients_by_list @ 96 ;\r
-       silc_client_get_clients_local @ 97 ;\r
-       silc_client_get_server @ 98 ;\r
-       silc_client_get_server_by_id @ 99 ;\r
-       silc_client_init @ 100 ;\r
-       silc_client_key_agreement @ 101 ;\r
-       silc_client_list_channel_private_keys @ 102 ;\r
-       silc_client_list_private_message_keys @ 103 ;\r
-       silc_client_notify_by_server @ 105 ;\r
-       silc_client_packet_process @ 106 ;\r
-       silc_client_packet_send @ 107 ;\r
-       silc_client_packet_send_real @ 108 ;\r
-       silc_client_perform_key_agreement @ 109 ;\r
-       silc_client_perform_key_agreement_fd @ 110 ;\r
-       silc_client_private_message @ 111 ;\r
-       silc_client_private_message_key @ 112 ;\r
-       silc_client_process_failure @ 113 ;\r
-       silc_client_protocol_ke_send_packet @ 114 ;\r
-       silc_client_protocol_ke_set_keys @ 115 ;\r
-       silc_client_protocol_ke_verify_key @ 116 ;\r
-       silc_client_protocols_register @ 117 ;\r
-       silc_client_protocols_unregister @ 118 ;\r
-       silc_client_receive_channel_key @ 119 ;\r
-       silc_client_receive_new_id @ 120 ;\r
-       silc_client_remove_from_channels @ 121 ;\r
-       silc_client_replace_from_channels @ 122 ;\r
-       silc_client_run @ 123 ;\r
-       silc_client_save_channel_key @ 124 ;\r
-       silc_client_send_channel_message @ 125 ;\r
-       silc_client_command_send @ 126 ;\r
-       silc_client_send_key_agreement @ 127 ;\r
-       silc_client_send_private_message @ 128 ;\r
-       silc_client_send_private_message_key @ 129 ;\r
-       silc_client_start_key_exchange @ 131 ;\r
-       silc_client_stop @ 132 ;\r
-       silc_idlist_get_client @ 137 ;\r
-       silc_client_abort_key_agreement @ 138 ;\r
-       silc_client_set_away_message @ 139 ;\r
-       silc_client_request_authentication_method @ 140 ;\r
-       silc_client_file_send @ 141 ;\r
-       silc_client_file_receive @ 142 ;\r
-       silc_client_file_close @ 143 ;\r
-       silc_client_command_register @ 144 ;\r
-       silc_client_command_unregister @ 145 ;\r
-       silc_client_commands_register @ 146 ;\r
-       silc_client_commands_unregister @ 147 ;\r
-       silc_client_command_call @ 148 ;\r
-       silc_client_command_reply_quit @ 149 ;\r
-       silc_client_run_one @ 150 ;\r
-       silc_client_on_channel @ 151 ;\r
-       silc_client_current_channel_private_key @ 152;\r
-        silc_client_attribute_add @ 153 ;\r
-        silc_client_attribute_del @ 154 ;\r
-        silc_client_attributes_get @ 155 ;\r
-        silc_client_attributes_request @ 156 ;\r
-       silc_client_get_channel_resolve @ 157 ;\r
-       silc_client_get_clients_by_channel @ 158 ;\r
+;
+; Exports file for SILC Client DLL.
+;
+; This file is generated from MinGW compiled object files using the
+; following command:
+;
+; dlltool --export-all --output-def libsilc.def libsilc.a
+;
+; ----------------------------------------------------------------------------
+;
+; If you edit this file by adding or removing any exports be sure to
+; preserve the ordinal values (the @ n in the exports) and add new exports
+; always at the end of the list with new ordinal value. Do not ever
+; add new export with old ordinal value if you need to preserve backwards
+; compatiblity. -Pekka
+;
+EXPORTS
+       silc_ske_check_version @ 1 ;
+       silc_client_add_channel_private_key @ 2 ;
+       silc_client_add_connection @ 3 ;
+       silc_client_add_private_message_key @ 4 ;
+       silc_client_add_private_message_key_ske @ 5 ;
+       silc_client_add_socket @ 6 ;
+       silc_client_alloc @ 7 ;
+       silc_client_channel_message @ 8 ;
+       silc_client_close_connection @ 9 ;
+       silc_client_command_alloc @ 10 ;
+       silc_client_command_ban @ 11 ;
+       silc_client_command_close @ 12 ;
+       silc_client_command_cmode @ 13 ;
+       silc_client_command_connect @ 14 ;
+       silc_client_command_cumode @ 15 ;
+       silc_client_command_dup @ 16 ;
+       silc_client_command_find @ 17 ;
+       silc_client_command_free @ 18 ;
+       silc_client_command_get_channel_by_id_callback @ 19 ;
+       silc_client_command_get_client_by_id_callback @ 20 ;
+       silc_client_command_get_client_callback @ 21 ;
+       silc_client_command_get_clients_list_callback @ 22 ;
+       silc_client_command_getkey @ 23 ;
+       silc_client_command_identify @ 24 ;
+       silc_client_command_info @ 25 ;
+       silc_client_command_invite @ 26 ;
+       silc_client_command_join @ 27 ;
+       silc_client_command_kick @ 28 ;
+       silc_client_command_kill @ 29 ;
+       silc_client_command_leave @ 30 ;
+       silc_client_command_list @ 31 ;
+       silc_client_command_motd @ 32 ;
+       silc_client_command_nick @ 33 ;
+       silc_client_command_oper @ 34 ;
+       silc_client_command_pending @ 35 ;
+       silc_client_command_pending_check @ 36 ;
+       silc_client_command_pending_del @ 37 ;
+       silc_client_command_ping @ 38 ;
+       silc_client_command_quit @ 39 ;
+       silc_client_command_reply_ban @ 40 ;
+       silc_client_command_reply_close @ 41 ;
+       silc_client_command_reply_cmode @ 42 ;
+       silc_client_command_reply_connect @ 43 ;
+       silc_client_command_reply_cumode @ 44 ;
+       silc_client_command_reply_free @ 45 ;
+       silc_client_command_reply_getkey @ 46 ;
+       silc_client_command_reply_identify @ 47 ;
+       silc_client_command_reply_info @ 48 ;
+       silc_client_command_reply_invite @ 49 ;
+       silc_client_command_reply_join @ 50 ;
+       silc_client_command_reply_kick @ 51 ;
+       silc_client_command_reply_kill @ 52 ;
+       silc_client_command_reply_leave @ 53 ;
+       silc_client_command_reply_list @ 54 ;
+       silc_client_command_reply_motd @ 55 ;
+       silc_client_command_reply_nick @ 56 ;
+       silc_client_command_reply_oper @ 57 ;
+       silc_client_command_reply_ping @ 58 ;
+       silc_client_command_reply_process @ 59 ;
+       silc_client_command_reply_shutdown @ 60 ;
+       silc_client_command_reply_silcoper @ 61 ;
+       silc_client_command_reply_topic @ 62 ;
+       silc_client_command_reply_umode @ 63 ;
+       silc_client_command_reply_users @ 64 ;
+       silc_client_command_reply_whois @ 65 ;
+       silc_client_command_reply_whowas @ 66 ;
+       silc_client_command_shutdown @ 67 ;
+       silc_client_command_silcoper @ 68 ;
+       silc_client_command_topic @ 70 ;
+       silc_client_command_umode @ 71 ;
+       silc_client_command_users @ 72 ;
+       silc_client_command_whois @ 73 ;
+       silc_client_command_whowas @ 74 ;
+       silc_client_connect_to_server @ 75 ;
+       silc_client_del_channel @ 76 ;
+       silc_client_del_channel_private_key @ 77 ;
+       silc_client_del_channel_private_keys @ 78 ;
+       silc_client_del_client @ 79 ;
+       silc_client_del_client_entry @ 80 ;
+       silc_client_del_connection @ 81 ;
+       silc_client_del_private_message_key @ 82 ;
+       silc_client_del_server @ 83 ;
+       silc_client_del_socket @ 84 ;
+       silc_client_disconnected_by_server @ 85 ;
+       silc_client_error_by_server @ 86 ;
+       silc_client_free @ 87 ;
+       silc_client_free_channel_private_keys @ 88 ;
+       silc_client_free_private_message_keys @ 89 ;
+       silc_client_get_channel @ 90 ;
+       silc_client_get_channel_by_id @ 91 ;
+       silc_client_get_channel_by_id_resolve @ 92 ;
+       silc_client_get_client_by_id @ 93 ;
+       silc_client_get_client_by_id_resolve @ 94 ;
+       silc_client_get_clients @ 95 ;
+       silc_client_get_clients_by_list @ 96 ;
+       silc_client_get_clients_local @ 97 ;
+       silc_client_get_server @ 98 ;
+       silc_client_get_server_by_id @ 99 ;
+       silc_client_init @ 100 ;
+       silc_client_key_agreement @ 101 ;
+       silc_client_list_channel_private_keys @ 102 ;
+       silc_client_list_private_message_keys @ 103 ;
+       silc_client_notify_by_server @ 105 ;
+       silc_client_packet_process @ 106 ;
+       silc_client_packet_send @ 107 ;
+       silc_client_packet_send_real @ 108 ;
+       silc_client_perform_key_agreement @ 109 ;
+       silc_client_perform_key_agreement_fd @ 110 ;
+       silc_client_private_message @ 111 ;
+       silc_client_private_message_key @ 112 ;
+       silc_client_process_failure @ 113 ;
+       silc_client_protocol_ke_send_packet @ 114 ;
+       silc_client_protocol_ke_set_keys @ 115 ;
+       silc_client_protocol_ke_verify_key @ 116 ;
+       silc_client_protocols_register @ 117 ;
+       silc_client_protocols_unregister @ 118 ;
+       silc_client_receive_channel_key @ 119 ;
+       silc_client_receive_new_id @ 120 ;
+       silc_client_remove_from_channels @ 121 ;
+       silc_client_replace_from_channels @ 122 ;
+       silc_client_run @ 123 ;
+       silc_client_save_channel_key @ 124 ;
+       silc_client_send_channel_message @ 125 ;
+       silc_client_command_send @ 126 ;
+       silc_client_send_key_agreement @ 127 ;
+       silc_client_send_private_message @ 128 ;
+       silc_client_send_private_message_key_request @ 129 ;
+       silc_client_start_key_exchange @ 131 ;
+       silc_client_stop @ 132 ;
+       silc_idlist_get_client @ 137 ;
+       silc_client_abort_key_agreement @ 138 ;
+       silc_client_set_away_message @ 139 ;
+       silc_client_request_authentication_method @ 140 ;
+       silc_client_file_send @ 141 ;
+       silc_client_file_receive @ 142 ;
+       silc_client_file_close @ 143 ;
+       silc_client_command_register @ 144 ;
+       silc_client_command_unregister @ 145 ;
+       silc_client_commands_register @ 146 ;
+       silc_client_commands_unregister @ 147 ;
+       silc_client_command_call @ 148 ;
+       silc_client_command_reply_quit @ 149 ;
+       silc_client_run_one @ 150 ;
+       silc_client_on_channel @ 151 ;
+       silc_client_current_channel_private_key @ 152;
+        silc_client_attribute_add @ 153 ;
+        silc_client_attribute_del @ 154 ;
+        silc_client_attributes_get @ 155 ;
+        silc_client_attributes_request @ 156 ;
+       silc_client_get_channel_resolve @ 157 ;
+       silc_client_get_clients_by_channel @ 158 ;
+       silc_client_get_clients_whois @ 159 ;
+       silc_client_send_packet @ 160 ;
index 5b2a08bb0da1e9d715546e77c3d575ed1f553a5b..e75257f27de5fedbb48ba39439de10ead19e0093 100644 (file)
@@ -42,7 +42,7 @@ RSC=rc.exe
 # PROP Intermediate_Dir "Release"\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILCCLIENT_EXPORTS" /YX /FD /c\r
-# ADD CPP /nologo /MT /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "NDEBUG" /D "MP_API_COMPATIBLE" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILCCLIENT_EXPORTS" /D "DLL" /YX /FD /c\r
+# ADD CPP /nologo /MT /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "NDEBUG" /D "MP_API_COMPATIBLE" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILCCLIENT_EXPORTS" /D "DLL" /D "HAVE_SILCDEFS_H" /YX /FD /Zm300 /c\r
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
 # ADD BASE RSC /l 0x409 /d "NDEBUG"\r
@@ -69,7 +69,7 @@ LINK32=link.exe
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILCCLIENT_EXPORTS" /YX /FD /GZ /c\r
-# ADD CPP /nologo /MTd /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "_DEBUG" /D "MP_API_COMPATIBLE" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILCCLIENT_EXPORTS" /D "SILC_DEBUG" /D "DLL" /YX /FD /GZ /c\r
+# ADD CPP /nologo /MTd /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "_DEBUG" /D "SILC_DEBUG" /D "MP_API_COMPATIBLE" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBSILCCLIENT_EXPORTS" /D "DLL" /D "HAVE_SILCDEFS_H" /YX /FD /GZ /Zm300 /c\r
 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
 # ADD BASE RSC /l 0x409 /d "_DEBUG"\r
index 55f6bb347dbd441b2bd5443ffb32c28df7dd41cb..9d3197144e16e4fdb9075f3ef924436319eeb304 100644 (file)
@@ -41,7 +41,7 @@ RSC=rc.exe
 # PROP Intermediate_Dir "Release"\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
-# ADD CPP /nologo /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /YX /FD /c\r
+# ADD CPP /nologo /W2 /GX /O2 /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /D "HAVE_SILCDEFS_H" /YX /FD /Zm300 /c\r
 # ADD BASE RSC /l 0x409 /d "NDEBUG"\r
 # ADD RSC /l 0x409 /d "NDEBUG"\r
 BSC32=bscmake.exe\r
@@ -64,7 +64,7 @@ LIB32=link.exe -lib
 # PROP Intermediate_Dir "Debug"\r
 # PROP Target_Dir ""\r
 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
-# ADD CPP /nologo /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /YX /FD /GZ /c\r
+# ADD CPP /nologo /W2 /Gm /GX /ZI /Od /I ".\\" /I "..\\" /I "..\..\\" /I "..\..\includes" /I "..\..\lib\silccore" /I "..\..\lib\silcske" /I "..\..\lib\silcmath" /I "..\..\lib\silcmath\mpi" /I "..\..\lib\silcutil" /I "..\..\lib\silccrypt" /I "..\..\lib\silcsim" /I "..\..\lib\trq" /I "..\..\lib\silcclient" /I "..\..\lib\silcsftp" /I "..\..\lib\contrib" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "MP_API_COMPATIBLE" /D "HAVE_SILCDEFS_H" /YX /FD /GZ /c\r
 # ADD BASE RSC /l 0x409 /d "_DEBUG"\r
 # ADD RSC /l 0x409 /d "_DEBUG"\r
 BSC32=bscmake.exe\r
index a312361678abafaa75df04326e4d47a13a1b4e80..eb0d689113690c9056e7e5c0071c9338ec51100c 100644 (file)
 /* #undef HAVE_RTLD_LAZY */
 
 /* Types */
+/*
 #define SILC_SIZEOF_LONG_LONG 8
 #define SILC_SIZEOF_LONG 4
 #define SILC_SIZEOF_INT 4
 #define SILC_SIZEOF_SHORT 2
 #define SILC_SIZEOF_CHAR 1
 #define SILC_SIZEOF_VOID_P 4
+*/
 
 /* MP library */
 /* #undef SILC_MP_GMP */